Independent security review
"Safe to use in paranoid mode. Cautiously safe in active mode with read-only creds." — AI security agent (operated by an independent lead developer), April 29, 2026 (v1.0.6)
TL;DR
An AI security agent — operated by an independent lead developer in our community — ran a layer-by-layer review of Ghost-hunter v1.0.6 on launch day. The verdict is positive. Four gaps were documented. Three landed as merged code fixes in v1.0.8. One is by-design behavior. Nothing about this audit is hidden — everything below is the agent's actual finding, with our triage.
We're being explicit that the audit was AI-driven because (a) Ghost-hunter is itself an AI agent, so AI auditing AI is honest meta-context, and (b) it changes how you should weight the findings. AI agents are good at pattern recognition across a known taxonomy (the kind of thing that catches awk system() reachability or unredacted disk writes). They're not a substitute for a human red-team or a formal code audit — and we're not claiming they are.
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 agent 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 agent.
Documented gaps — all addressed in v1.0.8
All four findings from the audit are closed. Three landed as deterministic code fixes; one was confirmed as by-design and explicitly documented. Each gap below carries the merged-PR link so anyone can audit our actual fix against the original finding.
✅ Gap 1 — Secrets persist unredacted on disk (was release-blocking; resolved in v1.0.8)
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 mattered: 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 were a real exposure vector — especially with backups, Time Machine, or cloud sync replicating the leak.
Fix shipped: ghosthunter#3 (closed via PR #8). New module ghosthunter.security.secrets_redactor runs a 9-pattern redaction over every disk-write path — AWS keys (AKIA / ASIA), GitHub tokens, Anthropic / OpenAI keys, JWTs (deliberately ordered before bearer tokens), bearer tokens, generic auth headers in shell / JSON / YAML forms, GCP service-account private_key JSON fields, and standalone PEM-armored private keys. Each match becomes [REDACTED:<type>]. New CLI command ghosthunter purge-history wipes pre-v1.0.8 chat history, audit log, and palace storage for users who already pasted sensitive output. Honest scope: the chat_history file is owned by prompt_toolkit and remains outside our redaction path — documented explicitly in SECURITY.md.
✅ Gap 2 — awk regex too permissive (was theoretical; resolved in v1.0.8)
Finding: ^awk(\s+.+)?$ allowed awk with any args. awk's system() builtin can spawn child processes; with non-blocklisted binaries (env, cat, ls) execution was theoretically possible. Mitigated in practice by Layer 6 (Sonnet semantic check) having to approve it first.
Fix shipped: ghosthunter#4 (closed via PR #6). Removed awk from SAFE_PIPE_TARGETS and added it to BLOCKED_PIPE_TARGETS (belt-and-braces — the blocklist check runs before the safe-list check in validate_pipes()). GCP and AWS reasoner prompts updated to drop awk from the listed safe pipes so Claude doesn't propose awk pipes the validator then rejects, wasting investigation budget. No legitimate Ghost-hunter use case requires awk; grep / cut / jq cover the same ground.
✅ Gap 3 — Prompt injection via pasted output (was soft; mitigated in v1.0.8)
Finding: if pasted command output contained "ignore previous instructions" or similar steering text, it could mislead Claude Opus toward wrong hypotheses. The deterministic command validator (layers 1–4) still held — the LLM could not be tricked into executing dangerous commands. But the conclusions of an investigation could be misled, wasting the budget cap on a bad hypothesis.
Fix shipped: ghosthunter#5 (closed via PR #7). New module ghosthunter.security.prompt_sanitizer strips seven known prompt-injection shapes ("ignore previous instructions", role-redefinition phrases, <system> / <admin> / <override> tags, "new instructions:" markers) from command output before the prompt is built. Output is also wrapped in a <command_output> defensive frame instructing Claude to treat the contents as untrusted data, not instructions. Honest scope: best-effort, not absolute — a novel injection shape we haven't seen will pass through. Treat investigation conclusions as advisory.
✅ Gap 4 — Layer 6 (Sonnet) approval bias (by design; documented in v1.0.8)
Finding: Sonnet's semantic check defaults toward approval. Layer 2 (the static allowlist) is the real deterministic gate.
Why it matters: the agent flagged this and accepted our explanation that it's 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 shipped: no code change. Layer-role explanation documented in SECURITY.md so this is explicit, not folklore.
v1.0.8 — released 2026-04-30
All three code-fix issues are closed:
- #3 — Redact secrets in chat_history / audit.log / palace ✅
- #4 — Tighten awk regex ✅
- #5 — Pre-paste prompt-injection sanitizer + doc warning ✅
Test suite grew from 1097 → 1255 tests, with +158 specifically for the new redactor / sanitizer / awk-block surfaces. Full release notes in the v1.0.8 changelog entry.
Note: v1.0.7 was the AGPL-3.0 relicense (Apr 28, 2026). v1.0.8 is the audit-fix release (Apr 30, 2026). Both were planned. The version-number jump skips no fixes — every audit finding above is in v1.0.8.
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 | AI security agent, operated by an independent lead developer in the Ghost-hunter community (attribution available on request) |
| Review type | Layer-by-layer code review (AI-driven; not a substitute for human red-team or formal audit) |
| 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) |
| Resolution | All addressed in v1.0.8, released 2026-04-30 |
| Time to fix | ~24 hours from audit delivery to merged main |
| Tracking | #3 ✅ · #4 ✅ · #5 ✅ |