Heimdall fingerprints the MCP config and server files that Claude Desktop, Claude Code, Cursor, Windsurf, and LM Studio load, and sounds the alarm the instant one is altered behind your back.
Named for the Norse watchman who guards the one bridge into Asgard and blows the horn when enemies approach — it guards your entry points, it watches and warns, and it doesn't pretend to be a wall. (Formerly Claude Defender, renamed once it grew past just Claude.)
- The threat: LOTL through MCP · How it works · A look inside
- Why the baseline can't be forged · Supported MCP hosts · Features
- Footprint · Benchmarks · Install · CLI
- What it is — and isn't · Roadmap · Security & license
Living-off-the-land attackers don't bring malware — they subvert the legitimate tools already on your machine. An MCP server is a perfect target: a trusted program your agent launches with full access. Poison its source, or slip a malicious server into a config an agent reads, and you have a trojanised entry point that runs every time — and nothing looks wrong. That's the point of LOTL.
Heimdall's job is to notice: it fingerprints every config and server file, and the instant one changes it shows you exactly what changed and lets you revert.
flowchart LR
subgraph Hosts["MCP hosts (auto-discovered)"]
A[Claude Desktop]
B[Claude Code]
C[Cursor]
D[Windsurf]
E[LM Studio]
end
Hosts -->|configs + server files| W[Filesystem watcher<br/>event-driven]
W --> Core[Detection core<br/>BLAKE3 fingerprints]
Core <-->|sign / verify| TR[trustroot<br/>keyed-MAC state]
TR <-->|MAC key| KS[(OS keystore)]
Logs[Claude logs] --> IA[Intrusion analysis]
Core --> V{Verdict}
IA --> V
V -->|clean| OK[Protected]
V -->|changed| DIFF[Diff → accept / revert]
V -->|state forged| TAMPER[Tamper alert]
Event-driven: it wakes only when a watched file changes, so at rest it does effectively no work, and detection is sub-second.
A tamper detector is only as trustworthy as its baseline. If that's an ordinary file, the attacker who edits your server can rewrite the baseline to match in the same breach — and the next check sees "no change."
Heimdall closes that with trustroot: every record (hashes,
snapshots, pending queue, audit log) is authenticated with a keyed BLAKE3
MAC whose key lives in your OS keystore (Credential Manager / Keychain /
Secret Service), not on disk.
sequenceDiagram
participant Atk as Attacker (file write)
participant State as baseline
participant KS as OS keystore
participant H as Heimdall
Atk->>State: rewrite hashes to hide the change
Note over Atk,KS: can't read the MAC key — it's in the keystore
H->>State: verify MAC
State-->>H: invalid → TAMPER 🔔
Forging the baseline now needs code execution as you, not just file-write — and deleting it doesn't help, since a missing baseline after setup is treated as tampering. It is not tamper-proof against an attacker who already has code-exec as you, or a compromised OS. See what it is — and isn't.
Auto-discovered — a host is watched only if its config exists. Install one later and a re-scan picks it up.
| Host | Config |
|---|---|
| Claude Desktop | %APPDATA%\Claude\claude_desktop_config.json (+ OS equivalents) |
| Claude Code | ~/.claude.json |
| Cursor | ~/.cursor/mcp.json |
| Windsurf | ~/.codeium/windsurf/mcp_config.json |
| LM Studio | ~/.lmstudio/mcp.json |
| Custom | any file you add in Settings |
- Integrity monitoring — real-time BLAKE3 fingerprints of each host's config and every server's source tree (not just the entry file — the modules it imports too, with lockfiles). On a change, a syntax-highlighted diff with per-file or all-at-once accept / revert (suspect version backed up first). Transient edits are caught even if reverted a moment later.
- Keystore-anchored baseline — the tamper-evidence above.
- Intrusion analysis — mines Claude's own logs (
mcp-info.json,mcp-server-*.log) into a per-server timeline, flagging recently-added, error-spikes, and orphans. Dismiss noise per-row or in bulk. - Quarantine — disable a suspect server (backed up, reversible).
- Audit report — export verdict + timeline + signed trail to Markdown/JSON.
- Headless CLI — same engine, no GUI, for scripting and always-on watching.
- Headless watcher (
watch): ~7.5 MB, ~0.1% CPU — no browser, no polling. - Desktop GUI: ~35 MB engine + WebView2 (Chromium) UI runtime (~310 MB, mostly shared OS pages, trimmed to tray). Inherent to any webview app.
Run the headless watch for always-on protection; open the GUI to review.
Reproducible (Ryzen 9 8945H, release) — see BENCHMARKS.md.
- BLAKE3 hashing 8.3 GiB/s; baseline verify ~27 µs (
cargo bench). check~40 ms on a typical config; 1000 servers in ~170 ms (~0.12 ms/file).- Detection sub-second (400 ms debounce + ~40 ms scan).
Grab the .msi or .exe from
Releases; it installs to the
tray, adds itself to startup, and establishes your baseline on first launch. The
installer is unsigned, so SmartScreen will warn — More info → Run anyway.
Verify the download against the SHA-256 published on the release.
There are no prebuilt macOS/Linux bundles yet, and Tauri can't cross-compile, so build the native installer on the target OS:
git clone https://github.com/2alf/Claude-Defender
cd Claude-Defender/claudeDefender-tauri
npm run setup # frontend deps
npm run tauri build # native bundle → src-tauri/target/release/bundle/
# or: npm run tauri dev # run without packagingPrerequisites: Rust + Node 18+. On Linux also install the webview/keystore build deps:
sudo apt install libdbus-1-dev libwebkit2gtk-4.1-dev libgtk-3-dev \
libappindicator3-dev librsvg2-dev patchelf pkg-configPlatform status: built and tested on Windows. The macOS and Linux paths (Keychain / Secret Service,
notify, native dialogs) are implemented but not yet verified — testers welcome.
The same core, headless:
heimdall watch # real-time monitoring (~8 MB, no GUI)
heimdall check # scan once — exit 0 clean / 1 changes / 2 tamper
heimdall accept | revert # accept/revert pending changes
heimdall reinit # rebuild baseline from current files (recovery)
heimdall intrusion # MCP install/run trace from logs
heimdall report # export an audit report (Markdown + JSON)
heimdall quarantine <server> # disable a suspect server (restore to undo)
heimdall status # watched files + last verdict
heimdall reset --yes # factory reset: wipe all state + keystore anchorsOverride paths with CLAUDE_DEFENDER_CONFIG / CLAUDE_DEFENDER_STATE_DIR.
The binary currently ships as
claude-defender-cli;heimdallis the rename target. The original Python script is retired tolegacy/.
A detective, tamper-evident control. Honesty about that is the point of the name.
Is: a real-time watcher that tells you what changed and when each server appeared; a trust anchor whose baseline can't be silently forged; one-click revert/quarantine.
Isn't: a wall (it warns; you decide) · tamper-proof against code-exec
as your user or a compromised OS · an antivirus/sandbox. For the
pre-execution shell side of LOTL (curl … | sh from a poisoned README), see the
sibling project whatif.
Signed releases + SBOM · remote anchoring of the audit chain · richer log↔config correlation · a non-WebView UI for a tens-of-MB GUI · full identifier rename (binaries, bundle id).
Open source. Disclosures welcome — see the
VDP. State lives
under MCPMonitor/ (all MAC-signed; hash-chained audit.log.json; pre-revert
backups/). GPL-3.0.
Thanks to everyone who's helped — Hall of Fame.

