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,rmall blocked at the entry point). - API key never written to disk — only read from
$ANTHROPIC_API_KEYat 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-auditruns in CI, with Dependabot configured.- 700+ security-specific tests.
SECURITY.mdis 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:
- #3 — Redact secrets in chat_history / audit.log / palace 🔴
- #4 — Tighten awk regex 🟡
- #5 — Pre-paste prompt-injection sanitizer + doc warning 🟡
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:
- Read SECURITY.md — written to be the starting document for a security review.
- Run the test suite —
pytest tests/exercises the 700+ security-specific tests. Negative cases for the validator are extensively covered. - Review the validator layers —
ghosthunter/validator/is where all 7 layers live. Each layer is a separate file with isolated unit tests. - Run paranoid mode on a synthetic CSV — observe behavior end-to-end without granting any cloud access.
- File anything you find as a GitHub issue or email
info@matrixgard.comfor 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
| Item | Detail |
|---|---|
| Reviewed version | Ghost-hunter v1.0.6 |
| Review date | April 29, 2026 |
| Reviewer | Independent security engineer (attribution available on request) |
| Review type | Layer-by-layer code review |
| Scope | Validator layers 1–7, secrets handling, dependency hygiene, CI supply chain |
| Verdict | Safe in paranoid mode · cautiously safe in active mode with read-only creds |
| Findings | 4 documented gaps (1 release-blocking, 2 theoretical, 1 by-design) |
| Open tracking | #3 · #4 · #5 |