VERDICT
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@VERDICT triage the memory capture from case 2025-001"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
VERDICT
Verifiable Evidence Reasoning for DFIR Investigation, Correlation, and Triage
An autonomous incident response analyst for the SANS SIFT Workstation. VERDICT extends Protocol SIFT with a read-only Custom MCP Server that turns the SIFT toolchain into typed, evidence-safe functions, and a Claude Code agent that forms hypotheses, corroborates every claim against the actual tool output, and self-corrects when sources disagree. It is built to match adversary speed without trading away the one thing a responder cannot lose: the integrity of the evidence and the truth of the findings.
Find Evil is about closing the gap between machine-speed attacks and human-speed response. In November 2025 Anthropic documented GTG-1002, a state-sponsored operation that drove Claude Code through reconnaissance, exploitation, and lateral movement at 80 to 90 percent autonomy, at request rates Anthropic called physically impossible for human operators. That was the offensive side. Protocol SIFT is the defensive answer, and Rob Lee's framing is exact: meet AI threat speed with defensive AI orchestration. VERDICT sharpens that orchestration by making the two failure modes of an autonomous responder (modifying evidence, and confidently reporting things that are not true) structurally impossible rather than merely discouraged.
Submission compliance (read this first)
Every required component, with its exact location. This project is complete and each item is linked below.
# | Required component | Where it is |
1 | Public code repository, open source | This repository. License below. |
2 | MIT or Apache 2.0 license file |
|
3 | README with setup instructions | |
4 | Live deployment or step-by-step run instructions | Run an investigation: one Docker command, or native on SIFT. |
5 | Text description of features and functionality | What it does below, and the Devpost project page. |
6 | Demo video (live terminal, audio narration, a self-correction) | Linked at the top of the Devpost page. A genuine asciinema terminal recording (the raw cast is committed at |
7 | Architecture diagram |
|
8 | Evidence dataset documentation |
|
9 | Accuracy report |
|
10 | Agent execution logs (traceable to tool executions) |
|
Architectural pattern used (per the brief): Pattern 2, Custom MCP Server, with Claude Code as the agentic engine. The three required capabilities (self-correction without human intervention, accuracy validation traceable to specific artifacts, and a structured investigative narrative) are demonstrated and described in How the design maps to the criteria.
A full self-audit against the official Stage One qualification prompt (the exact 12 checks
judges run, from the Judge Pack Appendix A) is in
SUBMISSION_CHECKLIST.md. The judges' non-negotiable
"trace any finding to its tool execution" check is done for you, with three worked
examples, in docs/three_claim_trace.md.
Related MCP server: SIFTGuard
What it does
You point VERDICT at a case (a disk image, a memory capture, a packet capture, or several of them from the same host) and it runs a complete triage the way a senior analyst would:
Orients on the evidence, recording a read-only chain-of-custody hash of every object before touching it.
Forms falsifiable hypotheses about what happened, and names the artifact that would confirm or kill each one.
Sequences tools adaptively. It runs the cheapest tool that can decide a hypothesis, reads the result, and lets that result choose the next tool. There is no fixed pipeline.
Corroborates every finding. Before any claim is allowed into the report, a deterministic engine re-reads the archived tool output and checks the asserted value is really there, in two independent sources, before it will call anything confirmed.
Self-corrects. When the cited output does not support a claim, the claim is caught as a likely hallucination and retracted. When two sources disagree, the agent runs a third to break the tie. Every change of mind is logged with the execution that triggered it.
Cross-checks sources. Given a disk and a memory image from one host, it compares them and flags discrepancies, which is where real intrusions hide.
Proves integrity and reports. It re-hashes the originals to prove they were never modified, then renders a structured investigative narrative and an honest accuracy report, both generated from the run ledger.
The result is an investigation a colleague could defend under cross-examination: every sentence traces to a specific tool execution, confirmed facts are separated from inferences, and the mistakes the agent caught itself making are on the record.
Why it is different from the baseline
The baseline Protocol SIFT is a Claude Code configuration: skill files plus behavioral
rules that hand the model a shell (Bash(*)) and ask it to be careful. Its guardrails
are prompt-based, and it feeds raw tool output into the model context, which is the
documented source of its hallucinations.
VERDICT changes the architecture, not just the prompt:
Concern | Baseline Protocol SIFT | VERDICT |
Evidence safety | Prompt says "never modify"; shell can still do anything | No shell, no write tool exists; files opened |
Hallucination control | "No hallucinations" instruction | Deterministic corroboration engine re-checks every claim against archived output |
Self-correction | "On failure, retry" instruction | Structural: an UNSUPPORTED or CONTRADICTED verdict forces a retraction or tie-break, logged with its trigger |
Context overload | Raw tool dumps into the model | Output parsed to compact summaries; raw archived to disk and referenced by id |
Audit trail | A summary line appended on stop | One structured provenance record per execution; every finding prints its exec ids |
Setup (two paths)
Path A: Docker (recommended for judges, one command)
Requirements: Docker, and Claude Code credentials (an ANTHROPIC_API_KEY, or a mounted
~/.claude). Nothing else.
git clone https://github.com/tejcodes-rex/verdict.git
cd verdict
docker build -t verdict:latest .The image carries a pinned subset of the SIFT toolchain (The Sleuth Kit, Volatility 3, Volatility 2.6 for older or 32-bit memory images, tshark, YARA, RegRipper, ExifTool) plus the agent runtime, so a run is reproducible on any machine without standing up a SIFT VM.
Path B: Native on the SANS SIFT Workstation
On a SIFT Workstation the tools are already installed. Install the server and the agent config:
git clone https://github.com/tejcodes-rex/verdict.git
cd verdict
pip3 install -e .
# Point Claude Code at the VERDICT MCP server and doctrine:
cp agent/CLAUDE.md ~/.claude/CLAUDE.md
cp agent/settings.json ~/.claude/settings.jsonThe MCP server resolves each tool at runtime (Volatility 3 at SIFT's /opt/volatility3*/vol.py,
Volatility 2 at SIFT's /usr/local/bin/vol.py, the rest on PATH), with VERDICT_<TOOL>
env overrides. Confirm your environment in one command:
python3 -m verdict.doctor # prints exactly which tool resolved, and whereThis was verified against a real SIFT tool layout: with vol deliberately not on PATH (as
on the OVA), VERDICT resolved Volatility 3 to python3 /opt/volatility3/vol.py, executed it
from that path, and ran a live investigation on the SIFT toolchain. See
docs/architecture.md and the accuracy report.
Run an investigation (for judges)
Sample evidence with published ground truth is documented in
docs/datasets.md. The Nitroba network case is small (53 MB) and
self-validating. To reproduce the headline run:
# 1. Fetch the sample evidence (script downloads from the official source and verifies hashes)
bash scripts/fetch_sample_evidence.sh
# 2. Run the full autonomous investigation in Docker.
# Evidence is mounted read-only; all output lands in ./work.
ANTHROPIC_API_KEY=sk-... \
EVIDENCE=$(pwd)/evidence/cases/nitroba \
WORK=$(pwd)/work \
docker compose run --rm --entrypoint bash verdict \
scripts/run_investigation.sh nitroba /evidence /work(The image entrypoint is the MCP server itself; --entrypoint bash runs the
investigation driver instead. If you prefer not to use compose, the equivalent
docker run is in docs/submission_guide.md.)
Agent authentication: the agent is Claude Code, so it needs your Claude credentials.
Either export ANTHROPIC_API_KEY (shown above), or, if you use a Claude subscription,
mount your existing login by adding -v $HOME/.claude:/root/.claude to the run. The
image never contains credentials; you supply them at run time. This is the only external
dependency, and it is one a judge of this event already has.
When it finishes, look in the newest ./work/run-*/ directory:
report.mdis the investigative narrative.accuracy_report.mdis the self-assessment, scored against ground truth.provenance.jsonlis the tool-execution audit trail.agent_stream.jsonlis the full agent execution log.
To run the agent against your own evidence, drop it in a directory and pass that as
EVIDENCE. The agent adapts to whatever data types it finds.
How the design maps to the judging criteria
Autonomous Execution Quality. The agent reasons over an explicit hypothesis ledger and re-sequences based on what it learns. Self-correction is structural: a corroboration verdict, computed from real tool output, forces it. The triggers are genuine (a value missing from output, two sources disagreeing), so they cannot be staged. See
docs/architecture.md.IR Accuracy. No claim reaches the confirmed list without its asserted value being present in two independent sources. Confirmed facts and inferences are labeled distinctly. The accuracy report is generated from the ledger, lists the hallucinations the agent caught, and is scored against published ground truth.
Breadth and Depth. Disk (The Sleuth Kit), memory (Volatility 3, Volatility 2, and symbol-free string analysis), network (tshark), Windows registry and program-execution evidence (RegRipper, Shimcache, Amcache), and IOC hunting (YARA) are handled deeply, with a grounded MITRE ATT&CK mapping. The Ali Hadi case, run on the genuine SIFT Workstation (
logs/examples/alihadi_sift/), correlates a 3 GB disk image and a 1 GB memory capture from one host: it reconstructs the full kill chain (DVWA command injection, an sqlmap SQL-injection campaign, three webshells including a Meterpreter payload, two attacker-created accounts in the on-disk SAM, and RDP persistence), and promotes the RDP-persistence finding to CONFIRMED only when the memory capture independently corroborates the same injected command. Cross-source corroboration of persistence is treated as a first-class, high-value finding.Constraint Implementation. Guardrails are architectural: the server exposes no destructive primitive, evidence is opened read-only (
O_RDONLY | O_NOFOLLOW), the memory tools refuse any Volatility dump plugin or output flag so a tool argument cannot become a write primitive, and a configuration layer denies the generic shell and write tools as defense in depth. The bypass test is documented in the accuracy report.Audit Trail Quality. One provenance record per execution; every finding prints its exec ids; the three-claim trace is mechanical. The provenance log is a tamper-evident hash chain, and each run is sealed with a verified chain head in
manifest.json.Usability and Documentation. One Docker command to run, and verified on the genuine SANS SIFT Workstation: the official OVA was booted and the full autonomous agent ran on it end to end (
logs/sift_verification/, and the SIFT run underlogs/examples/nitroba_sift/);python3 -m verdict.doctorreports tool resolution on any host. Ships ground-truth samples, committed runs, a live investigation view (scripts/agent_live.py), and an honest head-to-head with the example submission (benchmark/VALHUNTIR_COMPARISON.md).
Every corroborated finding is also mapped to MITRE ATT&CK techniques (deterministically, grounded only in confirmed findings so it cannot hallucinate context), giving the analyst the kill-chain picture without the false-context risk of a knowledge-base lookup.
Repository layout
verdict/
verdict/ the Python package (MCP server, engine, tools, reports)
server.py the MCP server: typed read-only tools + reasoning tools
evidence.py read-only evidence vault and integrity guarantees
provenance.py per-execution audit records (JSONL)
corroborate.py deterministic claim verifier
ledger.py hypotheses, findings, self-correction events
tools/ sleuthkit, volatility3, tshark, plaso wrappers
report/ narrative and accuracy-report generators
agent/ the agentic engine config: doctrine + read-only permissions
scripts/ run an investigation, fetch sample evidence, score a run
groundtruth/ answer keys for scored cases
docs/ architecture, datasets, accuracy report, demo script
logs/examples/ a committed full run (agent stream + tool provenance)
tests/ smoke tests that exercise the stack on real evidenceLicense
MIT. See LICENSE. This project builds on the open-source Protocol SIFT and
SANS SIFT Workstation; the novel contribution (the read-only MCP server, the
corroboration engine, the hypothesis ledger, and the provenance and reporting layers) is
original work created for this event and is documented as such throughout.
Available Tools
34 toolsattack_mapA
Map the corroborated findings recorded so far to MITRE ATT&CK techniques. The mapping is deterministic and runs only over CONFIRMED and INFERRED findings, so the technique coverage is grounded in verified evidence and each technique cites the findings that evidence it. Use this near the end of an investigation to frame the kill chain.
Inputs: no named parameters. Returns: result
audit_get_execA
Fetch a provenance record by exec_id so any finding can be traced to the exact tool execution that produced it. Optionally include a slice of the archived raw output.
Inputs: exec_id (required), include_raw, raw_max. Returns: result
audit_list_execsA
List all tool executions in this run with their function and evidence digest.
Inputs: no named parameters. Returns: result
case_openA
Open an investigation. Lists evidence objects in the read-only evidence root and records the chain-of-custody hash of each. Call this first.
Inputs: case_name (required), summary. Returns: result
corroborate_claimA
Check a claim against archived output without recording a finding. Useful for testing whether a hypothesis is supported before committing to it.
Inputs: statement (required), citations (required), claim_type, conflicting_citations. Returns: result
evidence_verify_integrityA
Recompute every evidence hash and compare to the value recorded at case_open. Run at the end of an investigation to prove the originals were never modified.
Inputs: no named parameters. Returns: result
finding_proposeA
Propose a finding. The corroboration engine independently verifies it against archived tool output before the ledger records a verdict.
claim_type tells the engine what kind of claim this is: "observation" - a direct read of primary evidence (a value literally present in an artifact, e.g. a recipient address in a POST body or a process name in pslist). Confirmed when the value is really in the cited output. "inference" - an analytical conclusion (attribution, causation, intent). Confirmed only when independent sources agree; otherwise labeled an inference. Use this for anything that combines observations rather than quoting one.
Each citation is a dict: {exec_id, artifact, locator, asserted_value}. asserted_value is the exact string the claim depends on; the engine checks it is really in that execution's output. If the verdict comes back UNSUPPORTED, the claim is a likely hallucination: do not present it as fact, investigate further, then revise. If it comes back CONTRADICTED, an independent source disagrees: resolve it before it stands.
Inputs: hypothesis_id (required), statement (required), citations (required), claim_type, +2 more. Returns: result
finding_reviseA
Revise a finding's verdict and log the change as a self-correction event with its trigger. Use this after new evidence resolves a CONTRADICTED finding or after you retract an UNSUPPORTED claim.
Inputs: finding_id (required), to_verdict (required), reason (required), trigger_exec_id. Returns: result
fs_amcacheA
Program-execution evidence from Amcache.hve: executed binary full paths and their SHA-1 hashes. Find the Amcache.hve inode with fs_find first. Read-only via RegRipper.
Inputs: image (required), hive_inode (required), offset. Returns: result
fs_catC
Read the content of a file by inode from a disk image (icat), read-only.
Inputs: image (required), inode (required), offset, max_bytes. Returns: result
fs_findA
Find files by name anywhere in a disk image (e.g. name_pattern="webshell" or ".php" or "access.log"). Builds and caches a recursive listing so repeated searches on a large disk are fast. Returns matching paths with their inodes for fs_cat.
Inputs: image (required), name_pattern (required), offset. Returns: result
fs_listC
List files in a disk image (fls). Optionally start at a partition offset or inode.
Inputs: image (required), offset, inode, recursive. Returns: result
fs_partitionsC
List partitions in a disk image (mmls).
Inputs: image (required). Returns: result
fs_registryA
Parse a Windows registry hive from a disk image with RegRipper (read-only). Find the hive's inode first with fs_find (e.g. fs_find image "SAM" or "SYSTEM"), then run a plugin: samparse (local accounts, find attacker-created users), profilelist, run / soft_run (Run-key persistence), services, winlogon, shimcache, usbstor, networklist.
Inputs: image (required), hive_inode (required), plugin (required), offset. Returns: result
fs_shimcacheA
Program-execution evidence from the SYSTEM hive's Application Compatibility Cache (Shimcache): paths and timestamps of binaries that ran or were present. Find the SYSTEM hive inode with fs_find first. Read-only via RegRipper.
Inputs: image (required), hive_inode (required), offset. Returns: result
fs_timelineC
Generate a file system MAC timeline body and parse the most recent activity (fls -m + mactime).
Inputs: image (required), offset. Returns: result
hypothesis_addC
Record an investigative hypothesis to test. Returns its id (e.g. H01).
Inputs: statement (required), rationale. Returns: result
hypothesis_set_stateC
Update a hypothesis state: OPEN, SUPPORTED, REFUTED, or INCONCLUSIVE.
Inputs: hypothesis_id (required), state (required), rationale. Returns: result
mem_cmdlineC
Process command lines from a memory image (volatility3 cmdline).
Inputs: image (required). Returns: result
mem_imageinfoA
Detect the Volatility 2 profile for a memory image (KDBG scan). Use this when the Volatility 3 tools fail to auto-resolve a profile (older or 32-bit images). Returns the suggested profile to pass to mem_vol2.
Inputs: image (required). Returns: result
mem_malfindC
Injected or hidden code regions from a memory image (volatility3 malfind).
Inputs: image (required). Returns: result
mem_networkC
Network connections from a memory image (volatility3 netscan).
Inputs: image (required). Returns: result
mem_pluginA
Run a read-only volatility3 plugin by name to test a hypothesis. Plugins that write carved data to disk (dumpfiles, memdump, procdump, ...) and any output/dump flag are refused: VERDICT exposes no write primitive. Use inspection plugins (pslist, netscan, malfind, consoles, cmdline, dlllist, getsids, handles).
Inputs: image (required), plugin (required), extra_args. Returns: result
mem_processesB
Process listing from a memory image (volatility3 pslist + pstree).
Inputs: image (required). Returns: result
mem_stringsA
Search a memory image for a literal string and return byte offsets (strings + grep, no symbol table required). Use this for cross-source IOC correlation: confirm that an artifact found on disk (a webshell filename, an attacker IP, a created account name) is also resident in memory. Works on any raw memory image regardless of OS profile.
Inputs: image (required), pattern (required), ignore_case. Returns: result
mem_vol2A
Run a Volatility 2 plugin for full structured memory forensics on images Volatility 3 cannot load. Common plugins: pslist, pstree, psscan, netscan, connscan, sockets, malfind, cmdline, consoles, cmdscan, dlllist, getsids, handles. If profile is empty it is auto-detected (and cached). Returns structured rows with PIDs, addresses, etc. Dump/output plugins and flags are refused (no write primitive); use read-only plugins.
Inputs: image (required), plugin (required), profile, extra_args. Returns: result
network_dnsC
Distinct DNS queries with counts.
Inputs: pcap (required). Returns: result
network_httpC
HTTP requests with host, method, URI, and source IP.
Inputs: pcap (required). Returns: result
network_overviewB
Protocol hierarchy and top IP conversations for a packet capture.
Inputs: pcap (required). Returns: result
network_searchA
Targeted tshark extraction to test a specific hypothesis. display_filter is a Wireshark display filter; fields is a list of field names to extract. Example: display_filter="http.cookie", fields=["frame.number","ip.src","http.cookie"].
Inputs: pcap (required), display_filter (required), fields (required). Returns: result
network_smtpC
SMTP envelope and mail header fields (sender, recipient, subject).
Inputs: pcap (required). Returns: result
report_buildA
Build the structured investigative narrative and the accuracy report from the ledger and provenance. If ground_truth_path is given (a YAML answer key), the accuracy report scores findings against it.
Inputs: case_name, ground_truth_path. Returns: result
super_timelineC
Build a plaso super-timeline of a disk image and summarize it (log2timeline + psort).
Inputs: image (required). Returns: result
yara_scanA
Sweep an evidence object (disk or memory image) with a YARA rule and return matches with offsets. rules_text is the YARA rule source. Use to hunt webshell signatures, packer stubs, or campaign IOCs across an image. Read-only.
Inputs: target (required), rules_text (required). Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 34 tools
Each tool targets a distinct forensic task (file system, memory, network, hypotheses, findings). Some overlap exists between mem_plugin and mem_vol2 for Volatility plugins, and between fs_registry and fs_shimcache (both registry-related), but descriptions clearly differentiate them.
Tools follow a consistent domain_prefix naming pattern (e.g., fs_, mem_, network_). Within each domain, verb_noun patterns are used (finding_propose, hypothesis_add). Minor deviations like attack_map and super_timeline do not significantly harm predictability.
34 tools is on the higher end, but each tool addresses a specific forensic need (file system, memory, network, YARA, reporting, etc.). The count is justified given the comprehensive coverage of DFIR workflows.
The tool surface covers major investigation phases: acquisition (case_open), file system analysis, memory analysis, network analysis, hypothesis management, findings, and reporting. Minor gaps exist (e.g., Windows event log parsing), but core workflows are well-supported.
Related MCP Connectors
Governed MCP: agent audit, provenance, deterministic checks, and receipt-backed FragGate execution.
Control plane for autonomous software labor. Agents claim objectives over MCP with audit trail.
Remote MCP for A2A failure replay MCP, structured receipts, audit logs, and reviewer-ready evidence.
AI-security knowledge as MCP: standards-mapped tools (OWASP, NIST, MITRE) for AI agents.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceEnables autonomous digital forensics and incident response through 21 typed forensic tools covering disk, memory, registry, network, timeline, carving, and patterns, integrated with AI-driven reasoning and self-correction.MIT
- AlicenseNot gradedqualityBmaintenanceEnables autonomous digital forensics and incident response by wrapping SIFT Workstation tools as MCP tools and orchestrating a multi-agent AI pipeline for evidence analysis and remediation planning.2MIT
- AlicenseBqualityCmaintenanceAdversarial autonomous DFIR. A court of AI agents — Prosecutor, Defender, Arbiter — investigates disk and memory evidence through a typed, read-only MCP server.111MIT
- AlicenseNot gradedqualityDmaintenanceAn MCP server that transforms Claude Code into an autonomous DFIR analyst by providing typed, audited forensic tools for disk, memory, timeline, registry, and IOC analysis on the SANS SIFT Workstation.Apache 2.0