Thesis
Find Evil is an autonomous incident-response agent whose spine is grounded finding-confirmation. Every finding the agent drafts is adjudicated against the exact tool output that supports it — classified grounded, ungrounded, or contradicted — and a contradicted finding is re-investigated with a different tool before it is allowed into the report. The whole loop runs over a forensic MCP surface that is read-only by construction, so the guardrails are architectural, not prompt-based.
Find Evil's distinguishing choice is finding-level grounding: it adjudicates each individual finding against the evidence that produced it — not merely which tool to run — and backs the design with a measured accuracy number. A contradicted finding is re-investigated with a different tool rather than re-running the same one.
What it does
Find Evil drives a SANS SIFT Workstation through Protocol SIFT to investigate a disk, memory, log, or network artifact and produce a findings.json report where every finding carries its own provenance chain: finding → tool → command → output SHA256 → line span → timestamp.
The agent has two roles:
- Investigator — plans the investigation, calls forensic tools over MCP, and drafts findings, each one citing the specific tool execution that supports it.
- Skeptic — for each draft finding, re-fetches the cited tool output by hash and renders a verdict:
grounded(enters the report),ungrounded(dropped as a hallucination), orcontradicted(the output actively refutes the claim).
A contradicted finding does not trigger a re-run of the same tool. It dispatches a different tool or artifact to corroborate — for example, a registry-run-key persistence claim that a tool contradicts gets checked against Prefetch or Amcache — then reconciles the result and records the resolution in the finding's corroboration field. This is grounded self-correction, not blind retry.
Underneath sits a custom read-only forensic MCP server exposing 14 typed tool wrappers: volatility3 (malfind, psscan, pslist, pstree, dlllist, handles, cmdline, netscan), YARA, MFTECmd, EvtxECmd, RECmd, PECmd, and AmcacheParser. No generic shell tool exists. Each wrapper declares a pydantic input model, builds an argv list (never a shell string), runs the binary with shell=False, and JSON-parses the output before it reaches the model. Every call is hashed and written to an append-only audit log — the same hash a finding's provenance later resolves against.
How we built it
The agent loop is Claude Code extending the Protocol SIFT base, with the Skeptic as the novel layer. The pattern is a generate-then-adversarially-verify pipeline: a recall-biased discovery pass drafts findings, and a precision-biased skeptic adjudicates each one against its cited evidence and emits structured output.
The orchestrator runs run_tool → draft → finalize, where finalize is skeptic → corroborate → schema-validated emit. Components:
- MCP server (
mcp_server.py) — stdio server exposing only the typed, gated wrappers. - Tool wrappers (
tools/) — each subclassesReadOnlyTool; the base class handles safety-gating, subprocess, audit logging, and output capture. - Safety layer (
safety.py) —guard_argv(binary deny-list + shell-metacharacter rejection) andassert_read_only_path(no writes under/cases/,/mnt/,/media/,/evidence/). This is belt-and-suspenders with a Claude Codesettings.jsonwrite-deny, so two independent layers both have to fail before evidence can be mutated. - Audit log (
audit.py) — append-only JSONL: timestamp, argv, output SHA256, token estimate, exit code, duration. - Skeptic (
skeptic.py+prompts/skeptic_system.md+model_client.py) — batched per-finding adjudication. - Corroboration (
corroboration.py) — different-tool selection by category-affinity plus hints, resilient to unavailable tools, then reconciliation.
The full loop runs offline against bundled evidence fixtures using the local claude CLI as the model backend (--allowed-tools "" so the nested call has no tools) — no SIFT box and no API key are needed to run the 32-test suite or the demo.
Accuracy results
The hackathon scores IR accuracy (correctness, hallucination detection, finding confirmation) and audit-trail quality. We measured the component that drives both — the finding-confirmation skeptic — against a no-skeptic baseline that reports every draft, on two complementary evals.
External (DFIR-Metric). DFIR-Metric (Cherif et al., ICONIP 2025 spotlight) is a third-party, peer-reviewed benchmark — neither its evidence nor its answers are ours. From its CTF module we took every challenge whose answer is a single source IP (n=9) and posed the skeptic two claims per challenge over the same logs: the true malicious IP (should ground) and a benign IP from the same logs (a hallucination trap, should be rejected).
| Configuration | Precision | Recall | FP-rate | F1 |
|---|---|---|---|---|
| Baseline — no skeptic | 0.50 | 1.00 | 1.00 | 0.667 |
| With finding-confirmation skeptic | 1.00 | 0.78 | 0.00 | 0.875 |
All 9 benign trap IPs were rejected. The recall cost (2 of 9 true positives marked ungrounded) is the precision-first behavior the design and the self-correction literature predict; we report it rather than tune it away.
Controlled (incident_2026). A recall-biased investigator simulated by a fixed labeled draft set over a synthetic incident: 16 drafts = 8 true positives + 8 negatives (6 false-positive traps + 2 decoys), evidence replayed from fixtures (memory malfind, YARA, Windows event logs, registry).
| Configuration | Precision | Recall | FP-rate | F1 |
|---|---|---|---|---|
| Baseline — no skeptic | 0.50 | 1.00 | 1.00 | 0.667 |
| With finding-confirmation skeptic | 1.00 | 1.00 | 0.00 | 1.00 |
All 16 drafts adjudicated correctly. Notably, the "svchost.exe PID 1408 is a clean service" trap was returned as contradicted (not merely ungrounded) — the correct routing for a claim a tool output actively refutes, which is what the corroboration step exists to recover.
The honest headline: across a third-party benchmark and a controlled case, the finding-confirmation layer drove the false-positive rate from 1.0 to 0.0 (precision 0.5 → 1.0), at a recall cost of zero on the controlled set and 2/9 on the external set.
How it maps to the six judging criteria
- Autonomous Execution Quality (tiebreaker) — grounded self-correction is the spine: a contradicted finding is re-investigated with a different tool and reconciled before reporting. This follows the literature's clear finding that intrinsic self-correction degrades without an external oracle (CRITIC; "LLMs Cannot Self-Correct Reasoning Yet"); our oracle is the cited tool output.
- IR Accuracy — measured precision 1.00 / FP-rate 0.00 on both evals, with hallucinated findings dropped (
ungrounded) and refuted findings routed for corroboration (contradicted). - Breadth/Depth — 14 read-only wrappers spanning memory (volatility3 suite), disk/MFT (MFTECmd), logs (EvtxECmd), registry (RECmd, AmcacheParser), execution (PECmd), pattern-matching (YARA), and network (netscan). Depth on the confirmation loop over breadth on tool count.
- Constraint Implementation (architectural, not prompt-based) — read-only is enforced at two independent layers: the MCP wrapper (binary deny-list,
shell=False, argv-as-list, protected-path guard) and Claude Codesettings.jsonwrite-deny. The agent physically cannot issuerm,dd,shred,wget,curl, orssh. - Audit Trail Quality — every finding's provenance chain (
tool → command → output SHA256 → line span → timestamp) is the audit trail; a finding cannot be emitted unless it cites a concrete tool execution, and the skeptic re-fetches that exact output by hash to adjudicate. - Usability/Docs — offline demo and 32-test suite run without a SIFT box or API key;
README.md,docs/ARCHITECTURE.md, andevaluation/ACCURACY_REPORT.mddocument the design, security boundary, and reproducible measurement.
Challenges
The literature is blunt that LLMs are unreliable self-validators — intrinsic self-correction can make reasoning worse, not better. The design consequence shaped the whole build: self-correction here is never pure introspection; the skeptic re-fetches the exact tool output by hash and adjudicates against it, and corroboration reaches for a different tool rather than re-running the same one.
Grounding had to be mechanical, not vibes. A finding cannot exist without citing a concrete tool execution, and the cited output is content-addressed by SHA256 so the skeptic adjudicates against the same bytes the investigator saw — not a paraphrase.
Decoupling from infrastructure mattered under a three-day clock. The whole loop is testable offline against captured fixtures via the local claude CLI, so the software spine could be built and measured without waiting on a live SIFT VM.
Accomplishments
- A working finding-confirmation loop with a measured, third-party-benchmark accuracy number.
- Read-only enforced at two independent architectural layers, exercised by tests, rather than asserted in a prompt.
- A provenance chain that is simultaneously the evidence-integrity mechanism and the submission's audit-trail deliverable.
- 32 passing tests and an offline demo that needs neither a SIFT box nor an API key, covering the confirm / retract / drop paths end-to-end.
What we learned
Eliminating hallucinated findings while keeping the grounded ones — not maximizing raw recall — is the capability the IR-accuracy and audit-trail criteria actually reward. A precision-first skeptic that drives FP-rate to zero, paired with corroboration to recover the true positives it conservatively drops, fits that incentive better than a high-recall report-everything baseline.
The recall cost is real and we left it visible: on the external set the skeptic marked 2 of 9 true positives ungrounded. That is the price of precision-first adjudication, and it is exactly what cross-tool corroboration exists to claw back (not exercised in the single-pass measurement above).
What's next
- Tool-execution-on-a-real-image evaluation — running Volatility et al. against an actual memory/disk capture with knowable ground truth. DFIR-Metric ships no images, so this requires the live forensic toolchain and is in progress.
- End-to-end recall — the numbers above measure the confirmation layer over a fixed draft set, not whether the investigator locates every artifact in an image. Closing that loop is the next measurement.
- Statistical robustness — small n (9 external + 16 controlled), single run each. Broadening the external set beyond single-IP log-analysis challenges and running repeated trials.
- Live SIFT + Protocol SIFT integration — registering the MCP server with Claude Code on a real SIFT Workstation and running the agent against mounted evidence.
License
MIT.
Log in or sign up for Devpost to join the conversation.