Skip to content

SIFT adapter layer

Bang Juwon edited this page May 14, 2026 · 5 revisions

SIFT Workstation tool adapter layer

The SIFT adapter layer (dart_mcp/sift_adapters/) brings agentic-dart into explicit alignment with the SANS FIND EVIL! 2026 hackathon's Pattern 2 — Custom MCP Server architectural pattern. It wraps the canonical SIFT Workstation DFIR toolchain in 25 typed read-only MCP adapters that share the same architectural guarantees as the 42 native pure-Python functions.

This page is the reference for what's exposed, how each adapter resolves its binary, and the design contract every adapter must satisfy.


Why the adapter layer exists

The hackathon's stated goal is to "make Protocol SIFT production-ready." Protocol SIFT's POC is a Claude Code agent + the SIFT Workstation's 200+ tools wired through MCP. The four supported architectural patterns are:

  1. Direct Agent Extension (Claude Code or OpenClaw) — extend Protocol SIFT's existing agent loop
  2. Custom MCP Serverthis is where agentic-dart lives
  3. Multi-Agent Frameworks (AutoGen, CrewAI, LangGraph)
  4. Alternative Agentic IDEs (Cursor, Cline, Aider)

Without the adapter layer, agentic-dart was technically a Pattern 2 Custom MCP Server, but with its own 35 forensic functions — not wrapping SIFT's tools. That left a structural gap: the implicit hackathon expectation is that submissions extend or wrap the SIFT toolchain. The adapter layer closes that gap without compromising the architectural guarantees that make agentic-dart distinctive.


What's exposed (25 adapters)

Volatility 3 (12 adapters)

Wraps vol from the Volatility Foundation v2.27 (released 2026-01-29). All twelve adapters return Volatility's CSV-rendered output parsed into Python dicts.

Adapter Plugin Use case
sift_vol3_windows_pslist windows.pslist.PsList Active Windows process list
sift_vol3_windows_pstree windows.pstree.PsTree Parent-child chain (catch macro execution patterns)
sift_vol3_windows_psscan windows.psscan.PsScan Hidden processes (DKOM diff vs. pslist)
sift_vol3_windows_cmdline windows.cmdline.CmdLine Per-process command lines (LotL hunting)
sift_vol3_windows_netscan windows.netscan.NetScan Active TCP/UDP connections
sift_vol3_windows_malfind windows.malfind.Malfind RWX injected code regions
sift_vol3_windows_dlllist windows.dlllist.DllList Loaded DLLs per process
sift_vol3_windows_svcscan windows.svcscan.SvcScan Service install (PsExec lateral movement)
sift_vol3_windows_runkey windows.registry.printkey.PrintKey Run-key persistence
sift_vol3_linux_pslist linux.pslist.PsList Linux active processes
sift_vol3_linux_bash linux.bash.Bash In-memory bash history (recovers wiped ~/.bash_history)
sift_vol3_mac_bash mac.bash.Bash macOS in-memory bash history

Eric Zimmerman tools (8 adapters)

Wraps the .NET 6 cross-platform builds of Eric Zimmerman's tools, which are bundled in /opt/EricZimmermanTools/ on the SIFT Workstation.

Adapter Tool Use case
sift_mftecmd_parse MFTECmd Full $MFT to structured rows
sift_mftecmd_timestomp MFTECmd $SI < $FN anomaly detection (T1070.006) — pairs with [Cheatsheet] mft-timestomp-detection
sift_evtxecmd_parse EvtxECmd EVTX to structured rows
sift_evtxecmd_filter_eids EvtxECmd Filtered to "heavy hitter" 12 EIDs (4624/4625/4672/4688 etc. + Sysmon 1/3/11/13 + PowerShell 4104)
sift_pecmd_parse PECmd Prefetch (.pf) records with FilesLoaded
sift_pecmd_run_history PECmd Per-executable last-N runs sorted by RunCount
sift_recmd_run_batch RECmd Run a batch file (default: ASEPs.reb — 50+ persistence locations)
sift_recmd_query_key RECmd Targeted registry key query
sift_amcacheparser_parse AmcacheParser Amcache.hve full parse with file SHA-1

YARA (2 adapters)

Wraps the YARA C binary (pre-installed on SIFT at /usr/bin/yara).

Adapter Use case
sift_yara_scan_file Scan a single file with a rules file or compiled rules
sift_yara_scan_dir Recursive directory scan

Plaso (2 adapters)

Wraps log2timeline + psort — the heavyweight super-timeline tool.

Adapter Use case
sift_plaso_log2timeline Generate .plaso storage from disk image / mount / single artifact
sift_plaso_psort Filter + render an existing .plaso to L2T CSV

How each adapter resolves its binary

Every adapter resolves its binary through _which() in _common.py, which follows this order:

  1. Environment variable override — e.g. DART_VOLATILITY3_BIN=/opt/volatility3/vol.py
  2. shutil.which() lookup on PATH
  3. SiftToolNotFoundError with a helpful install hint

Override env vars (one per tool):

Adapter family Env var
Volatility 3 DART_VOLATILITY3_BIN
MFTECmd DART_MFTECMD_BIN
EvtxECmd DART_EVTXECMD_BIN
PECmd DART_PECMD_BIN
RECmd DART_RECMD_BIN
AmcacheParser DART_AMCACHEPARSER_BIN
YARA DART_YARA_BIN
Plaso DART_LOG2TIMELINE_BIN + DART_PSORT_BIN

This gives you three deployment options:

  • SIFT Workstation default — tools at canonical SIFT paths, just install agentic-dart and adapters work
  • Custom install location — set the env var per tool
  • No SIFT — adapters raise SiftToolNotFoundError, agent loop falls back to native pure-Python implementations

Architectural contract every adapter must satisfy

This is the contract that makes the SIFT adapter layer non-trivial. Anyone adding a new adapter to sift_adapters/ must satisfy all six:

1. Read-only EVIDENCE_ROOT enforcement

Input paths flow through safe_evidence_input() (which delegates to the parent package's _safe_resolve()). Path traversal, null bytes, and absolute escapes are blocked before subprocess is invoked.

2. SHA-256 audit-chain compatibility

Every adapter returns:

{
    "metadata": {
        "tool": "...",
        "<input>_sha256": "<sha256>",   # input file hash
        "csv_sha256": "<sha256>",        # output artifact hash
        "duration_ms": 1234,
    }
}

These hashes plug straight into dart_audit's chain, so downstream evidence integrity is provable across both layers.

3. Subprocess timeout by default

All run_tool() calls have a hard timeout (defaults: 10 min for small tools, 20 min for Volatility, 30 min for MFTECmd / EvtxECmd directories, 6 hours for log2timeline). Adapters can override via the timeout= parameter.

4. Structured output, not raw stdout

Tool stdout/CSV is parsed into Python dicts before reaching the LLM. The agent never sees raw shell output. This is critical because filenames in evidence may contain attacker-controlled text — feeding raw stdout to the LLM is a prompt-injection vector.

5. Graceful degradation

Missing binary → SiftToolNotFoundError with the env-var name and install hint. The agent loop is expected to catch this and fall back to native pure-Python implementations.

6. Schema parity

Each adapter is registered via @tool(name, description, schema). The schema is well-formed JSON Schema with type: object, declared properties, and required. This is verified by tests/test_sift_adapters.py::test_each_sift_adapter_has_valid_schema.


Verification

# Tool count
python3 -c "from dart_mcp import list_tools; print(len(list_tools()))"
# → 60 (42 native + 25 SIFT)

# Run the SIFT-adapter test suite
python3 tests/test_sift_adapters.py
# → ✓ All SIFT adapter tests passed

# Confirm full surface (existing + SIFT)
python3 tests/test_mcp_surface.py
# → test_registered_tools_are_exact_set OK
# → test_destructive_functions_are_not_exposed OK
# → test_calling_unregistered_function_raises OK

What this does NOT change

  • The 42 native pure-Python forensic functions are untouched. They remain the fresh-clone demo path.
  • The NEGATIVE surface (execute_shell, write_file, mount, umount, eval, etc.) is unchanged. No destructive primitive was added.
  • dart_corr contradiction triggers, dart_audit hash chain, and the senior-analyst playbook v3 all work identically — they consume tool outputs by structure, not by which layer produced them.
  • MITRE ATT&CK coverage is enhanced at the same 10/12 enterprise tactics (the new adapters add depth to existing tactics, not breadth across new ones).

See also

Agentic-DART

Concepts

The 5 packages

Reference

Running it

Case studies

Project


Project links

Clone this wiki locally