Independent security review

"Safe to use in paranoid mode. Cautiously safe in active mode with read-only creds." — Independent security engineer, April 29, 2026 (v1.0.6)

TL;DR

An independent security engineer reviewed Ghost-hunter v1.0.6 layer-by-layer on launch day. The verdict is positive. Four gaps were documented. Three are filed as open v1.0.7 issues on the repo. One is by-design behavior. Nothing about this audit is hidden — everything below is the auditor's actual finding, with our triage.

How to read this page

We commit to a standing rule: every external security review of Ghost-hunter is published here, in full, with the auditor's permission. Verdicts and gaps both. We don't curate-out the uncomfortable findings — surfacing them honestly is the credibility play.

If you're a security team evaluating Ghost-hunter for use on real billing data, this page + SECURITY.md is the starting point. Both are designed to make your review job easier, not harder.

What the auditor found well done

  • Security enforced in code, not prompts. Even a prompt-injected LLM hits deterministic regex layers 1–4 — the validator is not something the model can talk its way past.
  • Layer 1 fast-reject runs on the full command string before pipe splitting. So | awk 'system("curl...")' style attacks still get caught (curl, wget, nc, bash, python, rm all blocked at the entry point).
  • API key never written to disk — only read from $ANTHROPIC_API_KEY at runtime.
  • Subprocess sandbox — only provider-specific creds passed, not the full environment.
  • Cross-provider isolation — a GCP session cannot run AWS commands and vice versa.
  • Hard budget caps per investigation — 15 commands, $1 USD, 10 minutes.
  • GitHub Actions pinned to commit SHAs, not floating tags. Supply-chain aware.
  • pip-audit runs in CI, with Dependabot configured.
  • 700+ security-specific tests.
  • SECURITY.md is honest about limitations — "rare to see," per the auditor.

Documented gaps & how we're addressing them

🔴 Gap 1 — Secrets persist unredacted on disk (release-blocking for v1.0.7)

Finding: if a user pastes command output containing AWS keys, GCP service-account JSON, JWTs, or bearer tokens, those land unredacted in ~/.ghosthunter/chat_history, ~/.ghosthunter/audit.log, or ~/.ghosthunter/palace/. They sit on disk indefinitely.

Why it matters: the user's mental model in paranoid mode is "Ghost-hunter is read-only and safe — I can paste freely." That's true for billing data, but secrets in pasted output are a real exposure vector — especially with backups, Time Machine, or cloud sync replicating the leak.

Fix in flight: ghosthunter#3 — redaction layer covering AWS keys, GCP service accounts, JWTs, bearer tokens, common API key formats, plus a ghosthunter --purge-history CLI flag for users who already pasted sensitive data with v1.0.6.

🟡 Gap 2 — awk regex too permissive (theoretical)

Finding: ^awk(\s+.+)?$ allows awk with any args. awk's system() builtin can spawn child processes; with non-blocklisted binaries (env, cat, ls) execution is theoretically possible. Mitigated in practice by Layer 6 (Sonnet semantic check) having to approve it first.

Why it matters: no known exploit, but the kind of finding that keeps a security reviewer up at night — and it's cheap to close.

Fix in flight: ghosthunter#4 — either remove awk from the allowlist entirely (preferred) or denylist system(, getline, exec(, coprocess pipes, and string-piped commands.

🟡 Gap 3 — Prompt injection via pasted output (soft)

Finding: if pasted command output contains "ignore previous instructions" or similar steering text, it can mislead Claude Opus toward wrong hypotheses. The deterministic command validator (layers 1–4) still holds — the LLM cannot be tricked into executing dangerous commands. But the conclusions of an investigation can be misled, wasting the budget cap on a bad hypothesis.

Why it matters: worst case is a misdirected investigation. Not a security boundary breach — but a reliability one. Users won't blame the attacker; they'll blame the tool.

Fix in flight: ghosthunter#5 — pre-paste sanitizer stripping the most common injection patterns + defensive <command_output> prompt framing + an explicit doc warning. Defense in layers, not absolute.

🟢 Gap 4 — Layer 6 (Sonnet) approval bias (by design)

Finding: Sonnet's semantic check defaults toward approval. Layer 2 (the static allowlist) is the real deterministic gate.

Why it matters: the auditor noted this is intentional — Layer 2 is the boundary, Layer 6 is judgment-on-top. We don't want Layer 6 to be the load-bearing gate; we want it to be the explainer.

Action: no code change. Documenting the layer roles in a future "How the validator works" doc page so this is explicit, not folklore.

v1.0.7 release tracking

All three release-relevant fixes are open on GitHub:

When v1.0.7 ships, this page gets a "Resolved in v1.0.7" stamp on each gap, and the next audit's findings replace these.

For your security team

Ghost-hunter is open source under AGPL-3.0. If your team wants to commission their own review:

  1. Read SECURITY.md — written to be the starting document for a security review.
  2. Run the test suitepytest tests/ exercises the 700+ security-specific tests. Negative cases for the validator are extensively covered.
  3. Review the validator layersghosthunter/validator/ is where all 7 layers live. Each layer is a separate file with isolated unit tests.
  4. Run paranoid mode on a synthetic CSV — observe behavior end-to-end without granting any cloud access.
  5. File anything you find as a GitHub issue or email info@matrixgard.com for coordinated disclosure.

If your team produces a written review and is willing to share, we'll publish it here with attribution. We're committed to the audit ledger growing, not staying at one entry forever.

Audit metadata

ItemDetail
Reviewed versionGhost-hunter v1.0.6
Review dateApril 29, 2026
ReviewerIndependent security engineer (attribution available on request)
Review typeLayer-by-layer code review
ScopeValidator layers 1–7, secrets handling, dependency hygiene, CI supply chain
VerdictSafe in paranoid mode · cautiously safe in active mode with read-only creds
Findings4 documented gaps (1 release-blocking, 2 theoretical, 1 by-design)
Open tracking#3 · #4 · #5