Skip to content

2alf/Heimdall

Repository files navigation

Heimdall logo

Heimdall

The watchman for your local AI agents' MCP layer.

CI status Platform: Windows, macOS, Linux Tauri 2 License: GPL-3.0


Heimdall dashboard — you're protected

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.)


Contents


The threat: LOTL through MCP

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.

How it works

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]
Loading

Event-driven: it wakes only when a watched file changes, so at rest it does effectively no work, and detection is sub-second.

A look inside

Changes detected
Changes detected — a real syntax-highlighted diff with per-file or all-at-once accept / revert.
Baseline tamper detected
Baseline tamper — the keystore-anchored integrity alert, with one-click rebuild from the current files.
Settings
Settings — toggle the mascot, add custom files to watch, and manage the intrusion-notice ignore list.
Protected — logo mode
Protected (logo mode) — the same dashboard with the static crest instead of the animated mark.

Why the baseline can't be forged

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 🔔
Loading

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.

Supported MCP hosts

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

Features

  • 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.

Footprint

Footprint at rest

  • 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.

Benchmarks

Reproducible (Ryzen 9 8945H, release) — see BENCHMARKS.md.

Benchmark summary

  • 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).

Install

Windows — prebuilt installer

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.

Build from source — recommended; required for macOS & Linux

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 packaging

Prerequisites: 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-config

Platform 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.

CLI

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 anchors

Override paths with CLAUDE_DEFENDER_CONFIG / CLAUDE_DEFENDER_STATE_DIR.

The binary currently ships as claude-defender-cli; heimdall is the rename target. The original Python script is retired to legacy/.

What it is — and isn't

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.

Roadmap

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).

Security & license

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.