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, 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 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:

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:

  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
ReviewerAI security agent, operated by an independent lead developer in the Ghost-hunter community (attribution available on request)
Review typeLayer-by-layer code review (AI-driven; not a substitute for human red-team or formal audit)
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)
ResolutionAll addressed in v1.0.8, released 2026-04-30
Time to fix~24 hours from audit delivery to merged main
Tracking#3 ✅ · #4 ✅ · #5 ✅