Veritas MCP
Veritas MCP — evidence-grounded "Find Evil" DFIR triage
Veritas (Latin, "truth"). A custom Model Context Protocol server that lets an AI agent triage a compromised host the way a senior DFIR analyst does — and that makes the two failure modes the judges care about most, evidence spoliation and hallucinated findings, architecturally impossible rather than merely discouraged by a prompt.
SANS "Find Evil!" Hackathon submission — Approach #2 (custom MCP server).
The problem (and why prompts aren't enough)
The baseline approach to "agentic DFIR" hands a model a shell on a SIFT workstation and a prompt that says please be careful and don't make things up. Two things go wrong:
Spoliation. A shell can
dd,del, mount read-write, or exfiltrate. One bad tool call destroys the evidence and the case. A prompt asking the model to behave is not a control an examiner can testify to.Hallucination. LLMs assert tidy conclusions that the data never supported. In forensics an unsupported "finding" is not a minor error — it is the thing that gets a case thrown out.
Veritas removes both at the architecture level.
How Veritas is different
Concern | Prompt-only baseline | Veritas |
Destroying evidence | "Please don't." | No tool exists that writes to, deletes, or mounts evidence. Evidence handles are opened |
Running arbitrary commands |
| No shell tool. Only 8 typed, allow-listed, read-only forensic tools. Shell metacharacters and forbidden binaries are rejected in depth. |
Hallucinated findings | hope | Grounding enforcement: a finding that does not cite the |
"Confirmed" vs guess | undifferentiated prose | Explicit confidence tiers ( |
First-pass mistakes | shipped as final | Self-correcting loop: retracts false positives against a known-good baseline, fills gaps the correlation engine finds (timestomping), and promotes corroborated findings — iterating to a fixed point. |
Context-window overload | raw tool text dumped into the model | Raw output is parsed server-side into compact typed records; the model reasons over fields, not megabytes. |
Explainability | none | Append-only JSONL audit log. Every tool run gets a stable |
"Trust me, it works" | — | Reproducible accuracy benchmark vs documented ground truth, runnable offline with zero third-party deps. |
Headline result (reproducible: python -m veritas.benchmark)
On the bundled synthetic case WEBSRV01, the same engine with self-correction
turned off (the prompt-only baseline) vs on (Veritas):
TP | FP | FN | Precision | Recall | F1 | Hallucination | |
Prompt-only baseline | 6 | 1 | 2 | 0.857 | 0.75 | 0.80 | 0.143 |
Veritas | 8 | 0 | 0 | 1.00 | 1.00 | 1.00 | 0.00 |
The baseline misses timestomping and the C2 channel, and over-flags a
benign OneDriveStandaloneUpdater.exe. Veritas catches the timestomp via
$SI/$FN correlation, confirms the C2 across memory + network, and retracts
the OneDrive false positive against a known-good baseline.
Quick start (60 seconds, no dependencies)
# from the repo root — pure standard library, simulation mode
$env:PYTHONPATH = "src"
python -m veritas.cli triage # human-readable findings report
python -m veritas.benchmark # the accuracy table above
python -m pytest -q # 46 tests, incl. spoliation-impossibilityOr install it and use the console script:
pip install -e .
veritas triage
veritas benchmarkTo drive it from Claude Code as a real MCP server:
pip install -e ".[mcp]"
# .mcp.json + claude/CLAUDE.md + claude/settings.json are included; see docs/TRY_IT_OUT.mdArchitecture at a glance
Host agent (Claude Code)
│ MCP (stdio) — only typed, read-only tools are exposed
▼
┌──────────────────────── Veritas MCP server ────────────────────────┐
│ 8 forensic tools ──► Executor (allow-list, shell=False) ──► EvidenceGuard │
│ │ │ (O_RDONLY) │
│ ▼ ▼ │
│ Parsers (raw→typed) AuditLog (append-only JSONL, exec_id) │
│ │ ▲ │
│ ▼ │ grounding check │
│ TriageLoop ──► FindingStore (rejects ungrounded; confidence tiers) │
│ │ ▲ │
│ ▼ │ │
│ CorrelationEngine + KnownGoodBaseline (self-correction) │
└─────────────────────────────────────────────────────────────────────────┘
│ writes ONLY to: exports/ analysis/ reports/ (never evidence)Full diagram, trust boundaries, and the prompt-guardrails vs. architectural-guardrails distinction are in docs/ARCHITECTURE.md.
Repository map
Path | What it is |
| The engine (stdlib-only core; |
| Synthetic but internally-consistent intrusion + simulated tool output |
| Documented ground truth used by the benchmark |
| 46 tests, including proofs that spoliation/hallucination are blocked |
| A real captured audit trail from one triage run |
|
|
| MCP server registration for Claude Code |
| The eight submission documents (see below) |
Submission documents
This README — overview & quick start.
docs/ARCHITECTURE.md — design, trust boundaries, guardrail taxonomy.
docs/ACCURACY_REPORT.md — methodology + reproducible numbers.
docs/DATASET.md — the synthetic case, how it was built, and why it's safe.
docs/TRY_IT_OUT.md — step-by-step, incl. Claude Code wiring.
docs/DEMO_SCRIPT.md — the 5-minute demo-video script.
docs/SUBMISSION.md — Devpost write-up / story & judging-criteria map.
logs/sample_agent_execution.jsonl— sample agent execution log (chain of custody).
License
MIT — see LICENSE. All bundled case data is synthetic; no real systems, persons, or indicators are represented.