oath-mcp 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. oath_mcp-0.1.0/.gitignore +89 -0
  2. oath_mcp-0.1.0/CITATION.cff +22 -0
  3. oath_mcp-0.1.0/LICENSE +21 -0
  4. oath_mcp-0.1.0/PKG-INFO +276 -0
  5. oath_mcp-0.1.0/README.md +203 -0
  6. oath_mcp-0.1.0/corpus/.gitkeep +0 -0
  7. oath_mcp-0.1.0/docker/eztools/Dockerfile +42 -0
  8. oath_mcp-0.1.0/docker/eztools/dotnet-tools.json +46 -0
  9. oath_mcp-0.1.0/docker-compose.yml +86 -0
  10. oath_mcp-0.1.0/docs/ACCURACY.md +163 -0
  11. oath_mcp-0.1.0/docs/ARCHITECTURE.md +173 -0
  12. oath_mcp-0.1.0/docs/ARTIFACT.md +48 -0
  13. oath_mcp-0.1.0/docs/DATASETS.md +168 -0
  14. oath_mcp-0.1.0/docs/DEVPOST.md +144 -0
  15. oath_mcp-0.1.0/docs/PUBLICATION.md +44 -0
  16. oath_mcp-0.1.0/docs/RECORDING.md +527 -0
  17. oath_mcp-0.1.0/docs/TRY_IT_OUT.md +149 -0
  18. oath_mcp-0.1.0/docs/demo.svg +460 -0
  19. oath_mcp-0.1.0/logs/.gitkeep +0 -0
  20. oath_mcp-0.1.0/pyproject.toml +119 -0
  21. oath_mcp-0.1.0/scripts/bootstrap-forensic-tools.sh +206 -0
  22. oath_mcp-0.1.0/scripts/demo.py +238 -0
  23. oath_mcp-0.1.0/scripts/dry-run.sh +229 -0
  24. oath_mcp-0.1.0/scripts/export_sample_run.py +342 -0
  25. oath_mcp-0.1.0/scripts/install-on-sift.sh +337 -0
  26. oath_mcp-0.1.0/scripts/install-tools.sh +221 -0
  27. oath_mcp-0.1.0/scripts/nss_baseline.py +509 -0
  28. oath_mcp-0.1.0/scripts/oath-mcp.sh +49 -0
  29. oath_mcp-0.1.0/scripts/prepare-demo.sh +112 -0
  30. oath_mcp-0.1.0/scripts/render_accuracy.py +186 -0
  31. oath_mcp-0.1.0/scripts/show_self_correction.py +342 -0
  32. oath_mcp-0.1.0/src/oath/__init__.py +7 -0
  33. oath_mcp-0.1.0/src/oath/__main__.py +7 -0
  34. oath_mcp-0.1.0/src/oath/agent/__init__.py +0 -0
  35. oath_mcp-0.1.0/src/oath/agent/demo.py +436 -0
  36. oath_mcp-0.1.0/src/oath/agent/runner.py +284 -0
  37. oath_mcp-0.1.0/src/oath/benchmark/__init__.py +62 -0
  38. oath_mcp-0.1.0/src/oath/benchmark/claude_agent.py +391 -0
  39. oath_mcp-0.1.0/src/oath/benchmark/claude_nss_agent.py +293 -0
  40. oath_mcp-0.1.0/src/oath/benchmark/corpus.py +237 -0
  41. oath_mcp-0.1.0/src/oath/benchmark/gemini_nss_agent.py +256 -0
  42. oath_mcp-0.1.0/src/oath/benchmark/harness.py +214 -0
  43. oath_mcp-0.1.0/src/oath/benchmark/question.py +297 -0
  44. oath_mcp-0.1.0/src/oath/benchmark/scorer.py +193 -0
  45. oath_mcp-0.1.0/src/oath/cli.py +617 -0
  46. oath_mcp-0.1.0/src/oath/mcp/__init__.py +0 -0
  47. oath_mcp-0.1.0/src/oath/mcp/evidence_handle.py +182 -0
  48. oath_mcp-0.1.0/src/oath/mcp/persistence.py +181 -0
  49. oath_mcp-0.1.0/src/oath/mcp/server.py +760 -0
  50. oath_mcp-0.1.0/src/oath/mcp/tools/__init__.py +0 -0
  51. oath_mcp-0.1.0/src/oath/mcp/tools/enumerate_credential_artifacts.py +469 -0
  52. oath_mcp-0.1.0/src/oath/mcp/tools/find_strings_on_image.py +567 -0
  53. oath_mcp-0.1.0/src/oath/mcp/tools/parse_amcache.py +308 -0
  54. oath_mcp-0.1.0/src/oath/mcp/tools/parse_evtx.py +474 -0
  55. oath_mcp-0.1.0/src/oath/mcp/tools/parse_mft.py +383 -0
  56. oath_mcp-0.1.0/src/oath/mcp/tools/parse_prefetch.py +266 -0
  57. oath_mcp-0.1.0/src/oath/mcp/tools/parse_registry.py +435 -0
  58. oath_mcp-0.1.0/src/oath/mcp/tools/parse_usnjrnl.py +374 -0
  59. oath_mcp-0.1.0/src/oath/mcp/tools/plaso_supertimeline.py +514 -0
  60. oath_mcp-0.1.0/src/oath/mcp/tools/run_hayabusa.py +441 -0
  61. oath_mcp-0.1.0/src/oath/mcp/tools/vol3_query.py +354 -0
  62. oath_mcp-0.1.0/src/oath/narrator/__init__.py +34 -0
  63. oath_mcp-0.1.0/src/oath/narrator/terminal.py +386 -0
  64. oath_mcp-0.1.0/src/oath/receipt/__init__.py +0 -0
  65. oath_mcp-0.1.0/src/oath/receipt/notarized.py +383 -0
  66. oath_mcp-0.1.0/src/oath/witness/__init__.py +0 -0
  67. oath_mcp-0.1.0/src/oath/witness/claim.py +185 -0
  68. oath_mcp-0.1.0/src/oath/witness/ralph_wiggum.py +276 -0
  69. oath_mcp-0.1.0/src/oath/witness/verifier.py +366 -0
  70. oath_mcp-0.1.0/symbols/.gitkeep +0 -0
  71. oath_mcp-0.1.0/tests/integration/test_mcp_server.py +308 -0
  72. oath_mcp-0.1.0/tests/integration/test_spoliation.py +677 -0
  73. oath_mcp-0.1.0/tests/unit/test_agent_runner.py +279 -0
  74. oath_mcp-0.1.0/tests/unit/test_benchmark.py +436 -0
  75. oath_mcp-0.1.0/tests/unit/test_benchmark_nss.py +336 -0
  76. oath_mcp-0.1.0/tests/unit/test_claude_agent.py +210 -0
  77. oath_mcp-0.1.0/tests/unit/test_claude_nss_agent.py +188 -0
  78. oath_mcp-0.1.0/tests/unit/test_enumerate_credential_artifacts.py +280 -0
  79. oath_mcp-0.1.0/tests/unit/test_find_strings_on_image.py +287 -0
  80. oath_mcp-0.1.0/tests/unit/test_gemini_nss_agent.py +131 -0
  81. oath_mcp-0.1.0/tests/unit/test_narrator.py +221 -0
  82. oath_mcp-0.1.0/tests/unit/test_notarized.py +198 -0
  83. oath_mcp-0.1.0/tests/unit/test_parse_amcache.py +134 -0
  84. oath_mcp-0.1.0/tests/unit/test_parse_evtx.py +299 -0
  85. oath_mcp-0.1.0/tests/unit/test_parse_mft.py +225 -0
  86. oath_mcp-0.1.0/tests/unit/test_parse_prefetch.py +131 -0
  87. oath_mcp-0.1.0/tests/unit/test_parse_registry.py +285 -0
  88. oath_mcp-0.1.0/tests/unit/test_parse_usnjrnl.py +202 -0
  89. oath_mcp-0.1.0/tests/unit/test_plaso_supertimeline.py +290 -0
  90. oath_mcp-0.1.0/tests/unit/test_ralph_wiggum.py +261 -0
  91. oath_mcp-0.1.0/tests/unit/test_run_hayabusa.py +272 -0
  92. oath_mcp-0.1.0/tests/unit/test_vol3_query.py +257 -0
  93. oath_mcp-0.1.0/tests/unit/test_witness_verifier.py +347 -0
  94. oath_mcp-0.1.0/uninstall.sh +115 -0
  95. oath_mcp-0.1.0/verify.sh +40 -0
  96. oath_mcp-0.1.0/web/README.md +42 -0
  97. oath_mcp-0.1.0/web/app.js +199 -0
  98. oath_mcp-0.1.0/web/build-data.sh +71 -0
  99. oath_mcp-0.1.0/web/data.js +497 -0
  100. oath_mcp-0.1.0/web/index.html +188 -0
  101. oath_mcp-0.1.0/web/styles.css +580 -0
@@ -0,0 +1,89 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ .venv/
8
+ venv/
9
+ env/
10
+ *.egg-info/
11
+ .pytest_cache/
12
+ .mypy_cache/
13
+ .ruff_cache/
14
+
15
+ # Node
16
+ node_modules/
17
+ .npm/
18
+
19
+ # Build artifacts
20
+ dist/
21
+ build/
22
+ *.whl
23
+
24
+ # Local secrets / state
25
+ .env
26
+ .env.local
27
+ *.token
28
+ *.key
29
+
30
+ # OS
31
+ .DS_Store
32
+ Thumbs.db
33
+
34
+ # Editor
35
+ .vscode/
36
+ .idea/
37
+
38
+ # Forensic corpora (big binaries — pulled by scripts, never committed)
39
+ corpus/
40
+ *.E01
41
+ *.dd
42
+ *.raw
43
+ *.vmem
44
+ *.mem
45
+ *.lime
46
+ *.dmp
47
+
48
+ # Volatility 3 symbol packs
49
+ symbols/
50
+
51
+ # Working state
52
+ .pair/
53
+ tmp/
54
+ *.log
55
+ logs/*.jsonl
56
+
57
+ # Benchmark intermediate output
58
+ benchmarks/runs/
59
+ benchmarks/cache/
60
+
61
+ # But keep these
62
+ !logs/.gitkeep
63
+ !corpus/.gitkeep
64
+ !symbols/.gitkeep
65
+
66
+ # Sandboxed local forensic tools (large, machine-specific)
67
+ .oath-tools/
68
+
69
+ # Per-run logs / envelope store / signing keys (machine-specific)
70
+ logs/
71
+ .oath/
72
+ keys/
73
+ .claude/
74
+ log2timeline-*.log.gz
75
+ psort-*.log.gz
76
+
77
+ # Paper-build artifacts (source + PDF are archived on Zenodo, not in-repo)
78
+ oath.tex
79
+ oath.pdf
80
+ oath.aux
81
+ oath.bbl
82
+ oath.blg
83
+ oath.log
84
+ oath.out
85
+ oath.bib
86
+ oath_*.png
87
+
88
+ # Local video composition (the recording lives outside the public repo)
89
+ video/
@@ -0,0 +1,22 @@
1
+ cff-version: 1.2.0
2
+ message: "If you use OATH, cite the preprint and the verifier artifact."
3
+ title: "OATH verifier artifact v0.1.0"
4
+ type: software
5
+ authors:
6
+ - family-names: Gharsallah
7
+ given-names: Malek
8
+ version: "v0.1.0"
9
+ date-released: "2026-06-05"
10
+ license: MIT
11
+ doi: "10.5281/zenodo.20549626"
12
+ url: "https://doi.org/10.5281/zenodo.20549626"
13
+ repository-code: "https://github.com/GharsallahDev/oath-mcp"
14
+ preferred-citation:
15
+ type: article
16
+ authors:
17
+ - family-names: Gharsallah
18
+ given-names: Malek
19
+ title: "OATH: Notarized Evidence Envelopes for LLM-Assisted Forensic Claims"
20
+ year: 2026
21
+ doi: "10.5281/zenodo.20549726"
22
+ url: "https://doi.org/10.5281/zenodo.20549726"
oath_mcp-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Malek Gharsallah
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,276 @@
1
+ Metadata-Version: 2.4
2
+ Name: oath-mcp
3
+ Version: 0.1.0
4
+ Summary: OATH — typed MCP server + verifier-gated evidence receipts for LLM-assisted digital forensics.
5
+ Project-URL: Homepage, https://github.com/GharsallahDev/oath-mcp
6
+ Project-URL: Repository, https://github.com/GharsallahDev/oath-mcp
7
+ Project-URL: Issues, https://github.com/GharsallahDev/oath-mcp/issues
8
+ Project-URL: Preprint (Zenodo), https://doi.org/10.5281/zenodo.20549726
9
+ Project-URL: Artifact (Zenodo), https://doi.org/10.5281/zenodo.20549626
10
+ Author-email: GharsallahDev <email@medsyn.solutions>
11
+ License: MIT
12
+ License-File: LICENSE
13
+ Keywords: claude-code,dfir,evidence,forensics,hayabusa,incident-response,mcp,sigma
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Intended Audience :: Information Technology
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: POSIX :: Linux
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Security
22
+ Classifier: Topic :: System :: Systems Administration
23
+ Requires-Python: >=3.11
24
+ Requires-Dist: anyio>=4.3.0
25
+ Requires-Dist: blake3>=0.4.0
26
+ Requires-Dist: click>=8.1.0
27
+ Requires-Dist: cryptography>=42.0.0
28
+ Requires-Dist: httpx>=0.27.0
29
+ Requires-Dist: mcp>=1.0.0
30
+ Requires-Dist: pydantic>=2.5.0
31
+ Requires-Dist: pynacl>=1.5.0
32
+ Requires-Dist: rich>=13.7.0
33
+ Requires-Dist: structlog>=24.1.0
34
+ Provides-Extra: all
35
+ Requires-Dist: anthropic>=0.40.0; extra == 'all'
36
+ Requires-Dist: construct>=2.10.0; extra == 'all'
37
+ Requires-Dist: dfir-iris-client>=2.0.0; extra == 'all'
38
+ Requires-Dist: google-cloud-aiplatform>=1.50.0; extra == 'all'
39
+ Requires-Dist: libfwsi-python>=20240315; extra == 'all'
40
+ Requires-Dist: matplotlib>=3.8.0; extra == 'all'
41
+ Requires-Dist: pandas>=2.2.0; extra == 'all'
42
+ Requires-Dist: python-evtx>=0.7.4; extra == 'all'
43
+ Requires-Dist: regipy>=4.0.0; extra == 'all'
44
+ Requires-Dist: scikit-learn>=1.4.0; extra == 'all'
45
+ Requires-Dist: volatility3>=2.7.0; extra == 'all'
46
+ Requires-Dist: yara-python>=4.5.0; extra == 'all'
47
+ Provides-Extra: benchmark
48
+ Requires-Dist: matplotlib>=3.8.0; extra == 'benchmark'
49
+ Requires-Dist: pandas>=2.2.0; extra == 'benchmark'
50
+ Requires-Dist: scikit-learn>=1.4.0; extra == 'benchmark'
51
+ Provides-Extra: claude
52
+ Requires-Dist: anthropic>=0.40.0; extra == 'claude'
53
+ Provides-Extra: dev
54
+ Requires-Dist: hypothesis>=6.100.0; extra == 'dev'
55
+ Requires-Dist: mypy>=1.9.0; extra == 'dev'
56
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
57
+ Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
58
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
59
+ Requires-Dist: ruff>=0.4.0; extra == 'dev'
60
+ Provides-Extra: iris
61
+ Requires-Dist: dfir-iris-client>=2.0.0; extra == 'iris'
62
+ Provides-Extra: memory
63
+ Requires-Dist: volatility3>=2.7.0; extra == 'memory'
64
+ Provides-Extra: parsers
65
+ Requires-Dist: construct>=2.10.0; extra == 'parsers'
66
+ Requires-Dist: libfwsi-python>=20240315; extra == 'parsers'
67
+ Requires-Dist: python-evtx>=0.7.4; extra == 'parsers'
68
+ Requires-Dist: regipy>=4.0.0; extra == 'parsers'
69
+ Requires-Dist: yara-python>=4.5.0; extra == 'parsers'
70
+ Provides-Extra: vertex
71
+ Requires-Dist: google-cloud-aiplatform>=1.50.0; extra == 'vertex'
72
+ Description-Content-Type: text/markdown
73
+
74
+ # OATH
75
+
76
+ Verifier-gated evidence receipts for LLM-assisted digital forensics.
77
+
78
+ [![Preprint DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.20549726.svg)](https://doi.org/10.5281/zenodo.20549726)
79
+ [![Artifact DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.20549626.svg)](https://doi.org/10.5281/zenodo.20549626)
80
+
81
+ OATH is a research prototype for making forensic claims replayable. It separates
82
+ what an LLM proposes from what the evidence proves: forensic tools produce signed
83
+ `Notarized<T>` envelopes, and the Witness Oath Verifier promotes only claims that
84
+ can be deterministically re-derived from the original evidence bytes.
85
+
86
+ This repository supports the published preprint:
87
+
88
+ > **OATH: Notarized Evidence Envelopes for LLM-Assisted Forensic Claims**
89
+ > Zenodo DOI: [10.5281/zenodo.20549726](https://doi.org/10.5281/zenodo.20549726)
90
+
91
+ The verifier artifact is archived separately at
92
+ [10.5281/zenodo.20549626](https://doi.org/10.5281/zenodo.20549626).
93
+
94
+ ## Relationship to Protocol SIFT
95
+
96
+ OATH extends [Protocol SIFT](https://github.com/teamdfir/protocol-sift) — the
97
+ open-source autonomous-DFIR baseline (Claude Code + five DFIR skill packs +
98
+ PDF reporter, installed under `~/.claude/`). Protocol SIFT provides the agent
99
+ framework; OATH layers a typed MCP-server tool surface, `Notarized<T>`
100
+ envelopes, and a verifier-gated promotion path on top. Both install scripts
101
+ (`scripts/install-tools.sh`, `scripts/install-on-sift.sh`) call Protocol SIFT's
102
+ own installer first, then install OATH. See
103
+ [docs/ARCHITECTURE.md §"How OATH extends Protocol SIFT"](docs/ARCHITECTURE.md#how-oath-extends-protocol-sift)
104
+ for the architectural diff.
105
+
106
+ If you already have Protocol SIFT installed (Claude Code present at
107
+ `~/.claude/CLAUDE.md` and the five skill packs at `~/.claude/skills/`), set
108
+ `OATH_SKIP_PROTOCOL_SIFT=1` before running either install script to skip the
109
+ baseline step:
110
+
111
+ ```bash
112
+ OATH_SKIP_PROTOCOL_SIFT=1 bash scripts/install-on-sift.sh
113
+ ```
114
+
115
+ ## Core Idea
116
+
117
+ LLM-assisted investigation fails dangerously when a fluent model summary is
118
+ treated as evidence. OATH treats that as a systems problem. A finding is not
119
+ accepted because the model said it; it is accepted only when it cites a signed
120
+ receipt whose contents replay.
121
+
122
+ Each `Notarized<T>` envelope binds:
123
+
124
+ - original evidence hash
125
+ - typed tool name and version
126
+ - canonical tool arguments
127
+ - raw tool-output hash
128
+ - parsed-data hash
129
+ - supporting byte offsets when available
130
+ - model identifier and prompt hash when an LLM contributed
131
+ - previous-envelope hash for tamper-evident sequencing
132
+ - Ed25519 signature over the signed header
133
+
134
+ The verifier then classifies claims as:
135
+
136
+ - `VERIFIED`: the receipt and predicate replay successfully
137
+ - `QUARANTINED`: the receipt is intact, but the cited claim is not supported
138
+ - `RALPH_WIGGUM`: evidence drift or receipt tampering is detected, forcing visible
139
+ abandonment and re-proposal
140
+
141
+ ## Results
142
+
143
+ The benchmark is DFIR-Metric Module III, using 510 scored string-search
144
+ questions in the local harness and a four-candidate answer budget.
145
+
146
+ | System | TUS@4 |
147
+ |---|---:|
148
+ | GPT-4.1 published baseline | 38.5% |
149
+ | OATH deterministic baseline, no LLM | 78.43% |
150
+ | OATH live agent with verifier | 92.75% |
151
+
152
+ The architectural result matters more than the model headline: typed tool
153
+ invocation plus deterministic replay removes a large class of free-form
154
+ script-generation failures before any model-specific capability is counted.
155
+
156
+ Full methodology and audit notes are in [docs/ACCURACY.md](docs/ACCURACY.md).
157
+
158
+ ## Artifact Release
159
+
160
+ A verifier-focused artifact release is archived on Zenodo:
161
+
162
+ - Artifact: [OATH verifier artifact v0.1.0](https://doi.org/10.5281/zenodo.20549626)
163
+ - Preprint: [OATH: Notarized Evidence Envelopes for LLM-Assisted Forensic Claims](https://doi.org/10.5281/zenodo.20549726)
164
+
165
+ The release is intended to let an independent reviewer answer the narrow
166
+ question: does the receipt, signature, canonicalization, replay, and
167
+ self-correction design work? It does not include private case data, signing
168
+ secrets, API keys, or operational prompts.
169
+
170
+ ## Quick Start
171
+
172
+ OATH is published as a Python MCP server. Four one-liners on a SANS SIFT
173
+ Workstation get you from cold boot to "Claude Code is driving 13 typed
174
+ forensic tools against your evidence":
175
+
176
+ ```bash
177
+ # 1. Protocol SIFT baseline (Claude Code + DFIR skill packs)
178
+ curl -fsSL https://raw.githubusercontent.com/teamdfir/protocol-sift/main/install.sh | bash
179
+
180
+ # 2. Forensic-binary bootstrap (.NET 9, EZ Tools, Hayabusa — what SIFT lacks)
181
+ curl -fsSL https://raw.githubusercontent.com/GharsallahDev/oath-mcp/main/scripts/bootstrap-forensic-tools.sh | bash
182
+ exec bash # pick up the new PATH
183
+
184
+ # 3. uv (if not already installed)
185
+ curl -LsSf https://astral.sh/uv/install.sh | sh && exec bash
186
+
187
+ # 4. Wire OATH into Claude Code (this is what goes on screen in the demo)
188
+ claude mcp add --transport stdio oath -- uvx oath-mcp
189
+ ```
190
+
191
+ Then start a session and confirm the 13 typed tools are connected:
192
+
193
+ ```bash
194
+ claude
195
+ # inside Claude:
196
+ /mcp # → oath: connected · 13 tools
197
+ ```
198
+
199
+ To use the operator CLI (`oath mount`, `oath verify`, `oath demo`) instead
200
+ of driving via Claude Code, install the package as a tool:
201
+
202
+ ```bash
203
+ uv tool install oath-mcp
204
+ oath mount path/to/evidence.E01
205
+ oath verify <envelope-id>
206
+ ```
207
+
208
+ Full forensic workstation setup, including the longer-form
209
+ `install-on-sift.sh` alternative and a non-SIFT Docker path, is documented
210
+ in [docs/TRY_IT_OUT.md](docs/TRY_IT_OUT.md).
211
+
212
+ ### Developing locally
213
+
214
+ For working on `src/oath/`:
215
+
216
+ ```bash
217
+ git clone https://github.com/GharsallahDev/oath-mcp-mcp
218
+ cd oath-mcp
219
+ uv venv && uv pip install -e ".[dev]"
220
+ PYTHONPATH=src python -m pytest tests/integration/test_spoliation.py -q
221
+ ```
222
+
223
+ ## Architecture
224
+
225
+ ```mermaid
226
+ flowchart LR
227
+ IMG["Evidence image"] --> HANDLE["Read-only EvidenceHandle"]
228
+ HANDLE --> TOOLS["Typed forensic tools"]
229
+ TOOLS --> ENV["Signed Notarized<T> envelope"]
230
+ LLM["LLM proposes typed arguments and claims"] --> TOOLS
231
+ LLM --> CLAIM["Claim cites envelope_id"]
232
+ CLAIM --> VERIFY{"Witness Oath Verifier"}
233
+ ENV --> VERIFY
234
+ VERIFY -->|receipt replays + predicate matches| OK["VERIFIED"]
235
+ VERIFY -->|receipt intact, predicate missing| Q["QUARANTINED"]
236
+ VERIFY -->|hash/signature/data drift| R["RALPH_WIGGUM"]
237
+ R --> LLM
238
+ ```
239
+
240
+ OATH uses a custom MCP-style tool surface with typed functions rather than an
241
+ arbitrary shell. The LLM can propose arguments and hypotheses; it cannot promote
242
+ its own findings. Promotion is reserved for the deterministic verifier.
243
+
244
+ Detailed trust-boundary notes are in [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md).
245
+
246
+ ## Repository Map
247
+
248
+ | Path | Purpose |
249
+ |---|---|
250
+ | `src/oath/receipt/` | `Notarized<T>` envelope, canonicalization, signatures, prompt hashing |
251
+ | `src/oath/mcp/` | Typed forensic tool surface and evidence-handle plumbing |
252
+ | `src/oath/witness/` | Verifier, claim predicates, self-correction events |
253
+ | `src/oath/benchmark/` | DFIR-Metric harness and scoring utilities |
254
+ | `tests/integration/test_spoliation.py` | Spoliation, data-integrity, chain, and Daubert-binding tests |
255
+ | `logs/self-correction-demo/` | Re-runnable self-correction artifact |
256
+ | `web/` | Static receipt explorer for signed sample envelopes |
257
+
258
+ ## What OATH Does Not Claim
259
+
260
+ OATH does not prove legal admissibility, certify tool correctness, make wrappers
261
+ honest by magic, prove general DFIR competence, or remove the need for examiner
262
+ review. It provides a concrete receipt and verifier pattern for making
263
+ LLM-assisted forensic claims auditable.
264
+
265
+ ## Documentation
266
+
267
+ - [Architecture](docs/ARCHITECTURE.md)
268
+ - [Artifact release notes](docs/ARTIFACT.md)
269
+ - [Publication and citation notes](docs/PUBLICATION.md)
270
+ - [Accuracy and benchmark notes](docs/ACCURACY.md)
271
+ - [Dataset documentation](docs/DATASETS.md)
272
+ - [Try-it-out instructions](docs/TRY_IT_OUT.md)
273
+
274
+ ## License
275
+
276
+ MIT. See [LICENSE](LICENSE).
@@ -0,0 +1,203 @@
1
+ # OATH
2
+
3
+ Verifier-gated evidence receipts for LLM-assisted digital forensics.
4
+
5
+ [![Preprint DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.20549726.svg)](https://doi.org/10.5281/zenodo.20549726)
6
+ [![Artifact DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.20549626.svg)](https://doi.org/10.5281/zenodo.20549626)
7
+
8
+ OATH is a research prototype for making forensic claims replayable. It separates
9
+ what an LLM proposes from what the evidence proves: forensic tools produce signed
10
+ `Notarized<T>` envelopes, and the Witness Oath Verifier promotes only claims that
11
+ can be deterministically re-derived from the original evidence bytes.
12
+
13
+ This repository supports the published preprint:
14
+
15
+ > **OATH: Notarized Evidence Envelopes for LLM-Assisted Forensic Claims**
16
+ > Zenodo DOI: [10.5281/zenodo.20549726](https://doi.org/10.5281/zenodo.20549726)
17
+
18
+ The verifier artifact is archived separately at
19
+ [10.5281/zenodo.20549626](https://doi.org/10.5281/zenodo.20549626).
20
+
21
+ ## Relationship to Protocol SIFT
22
+
23
+ OATH extends [Protocol SIFT](https://github.com/teamdfir/protocol-sift) — the
24
+ open-source autonomous-DFIR baseline (Claude Code + five DFIR skill packs +
25
+ PDF reporter, installed under `~/.claude/`). Protocol SIFT provides the agent
26
+ framework; OATH layers a typed MCP-server tool surface, `Notarized<T>`
27
+ envelopes, and a verifier-gated promotion path on top. Both install scripts
28
+ (`scripts/install-tools.sh`, `scripts/install-on-sift.sh`) call Protocol SIFT's
29
+ own installer first, then install OATH. See
30
+ [docs/ARCHITECTURE.md §"How OATH extends Protocol SIFT"](docs/ARCHITECTURE.md#how-oath-extends-protocol-sift)
31
+ for the architectural diff.
32
+
33
+ If you already have Protocol SIFT installed (Claude Code present at
34
+ `~/.claude/CLAUDE.md` and the five skill packs at `~/.claude/skills/`), set
35
+ `OATH_SKIP_PROTOCOL_SIFT=1` before running either install script to skip the
36
+ baseline step:
37
+
38
+ ```bash
39
+ OATH_SKIP_PROTOCOL_SIFT=1 bash scripts/install-on-sift.sh
40
+ ```
41
+
42
+ ## Core Idea
43
+
44
+ LLM-assisted investigation fails dangerously when a fluent model summary is
45
+ treated as evidence. OATH treats that as a systems problem. A finding is not
46
+ accepted because the model said it; it is accepted only when it cites a signed
47
+ receipt whose contents replay.
48
+
49
+ Each `Notarized<T>` envelope binds:
50
+
51
+ - original evidence hash
52
+ - typed tool name and version
53
+ - canonical tool arguments
54
+ - raw tool-output hash
55
+ - parsed-data hash
56
+ - supporting byte offsets when available
57
+ - model identifier and prompt hash when an LLM contributed
58
+ - previous-envelope hash for tamper-evident sequencing
59
+ - Ed25519 signature over the signed header
60
+
61
+ The verifier then classifies claims as:
62
+
63
+ - `VERIFIED`: the receipt and predicate replay successfully
64
+ - `QUARANTINED`: the receipt is intact, but the cited claim is not supported
65
+ - `RALPH_WIGGUM`: evidence drift or receipt tampering is detected, forcing visible
66
+ abandonment and re-proposal
67
+
68
+ ## Results
69
+
70
+ The benchmark is DFIR-Metric Module III, using 510 scored string-search
71
+ questions in the local harness and a four-candidate answer budget.
72
+
73
+ | System | TUS@4 |
74
+ |---|---:|
75
+ | GPT-4.1 published baseline | 38.5% |
76
+ | OATH deterministic baseline, no LLM | 78.43% |
77
+ | OATH live agent with verifier | 92.75% |
78
+
79
+ The architectural result matters more than the model headline: typed tool
80
+ invocation plus deterministic replay removes a large class of free-form
81
+ script-generation failures before any model-specific capability is counted.
82
+
83
+ Full methodology and audit notes are in [docs/ACCURACY.md](docs/ACCURACY.md).
84
+
85
+ ## Artifact Release
86
+
87
+ A verifier-focused artifact release is archived on Zenodo:
88
+
89
+ - Artifact: [OATH verifier artifact v0.1.0](https://doi.org/10.5281/zenodo.20549626)
90
+ - Preprint: [OATH: Notarized Evidence Envelopes for LLM-Assisted Forensic Claims](https://doi.org/10.5281/zenodo.20549726)
91
+
92
+ The release is intended to let an independent reviewer answer the narrow
93
+ question: does the receipt, signature, canonicalization, replay, and
94
+ self-correction design work? It does not include private case data, signing
95
+ secrets, API keys, or operational prompts.
96
+
97
+ ## Quick Start
98
+
99
+ OATH is published as a Python MCP server. Four one-liners on a SANS SIFT
100
+ Workstation get you from cold boot to "Claude Code is driving 13 typed
101
+ forensic tools against your evidence":
102
+
103
+ ```bash
104
+ # 1. Protocol SIFT baseline (Claude Code + DFIR skill packs)
105
+ curl -fsSL https://raw.githubusercontent.com/teamdfir/protocol-sift/main/install.sh | bash
106
+
107
+ # 2. Forensic-binary bootstrap (.NET 9, EZ Tools, Hayabusa — what SIFT lacks)
108
+ curl -fsSL https://raw.githubusercontent.com/GharsallahDev/oath-mcp/main/scripts/bootstrap-forensic-tools.sh | bash
109
+ exec bash # pick up the new PATH
110
+
111
+ # 3. uv (if not already installed)
112
+ curl -LsSf https://astral.sh/uv/install.sh | sh && exec bash
113
+
114
+ # 4. Wire OATH into Claude Code (this is what goes on screen in the demo)
115
+ claude mcp add --transport stdio oath -- uvx oath-mcp
116
+ ```
117
+
118
+ Then start a session and confirm the 13 typed tools are connected:
119
+
120
+ ```bash
121
+ claude
122
+ # inside Claude:
123
+ /mcp # → oath: connected · 13 tools
124
+ ```
125
+
126
+ To use the operator CLI (`oath mount`, `oath verify`, `oath demo`) instead
127
+ of driving via Claude Code, install the package as a tool:
128
+
129
+ ```bash
130
+ uv tool install oath-mcp
131
+ oath mount path/to/evidence.E01
132
+ oath verify <envelope-id>
133
+ ```
134
+
135
+ Full forensic workstation setup, including the longer-form
136
+ `install-on-sift.sh` alternative and a non-SIFT Docker path, is documented
137
+ in [docs/TRY_IT_OUT.md](docs/TRY_IT_OUT.md).
138
+
139
+ ### Developing locally
140
+
141
+ For working on `src/oath/`:
142
+
143
+ ```bash
144
+ git clone https://github.com/GharsallahDev/oath-mcp-mcp
145
+ cd oath-mcp
146
+ uv venv && uv pip install -e ".[dev]"
147
+ PYTHONPATH=src python -m pytest tests/integration/test_spoliation.py -q
148
+ ```
149
+
150
+ ## Architecture
151
+
152
+ ```mermaid
153
+ flowchart LR
154
+ IMG["Evidence image"] --> HANDLE["Read-only EvidenceHandle"]
155
+ HANDLE --> TOOLS["Typed forensic tools"]
156
+ TOOLS --> ENV["Signed Notarized<T> envelope"]
157
+ LLM["LLM proposes typed arguments and claims"] --> TOOLS
158
+ LLM --> CLAIM["Claim cites envelope_id"]
159
+ CLAIM --> VERIFY{"Witness Oath Verifier"}
160
+ ENV --> VERIFY
161
+ VERIFY -->|receipt replays + predicate matches| OK["VERIFIED"]
162
+ VERIFY -->|receipt intact, predicate missing| Q["QUARANTINED"]
163
+ VERIFY -->|hash/signature/data drift| R["RALPH_WIGGUM"]
164
+ R --> LLM
165
+ ```
166
+
167
+ OATH uses a custom MCP-style tool surface with typed functions rather than an
168
+ arbitrary shell. The LLM can propose arguments and hypotheses; it cannot promote
169
+ its own findings. Promotion is reserved for the deterministic verifier.
170
+
171
+ Detailed trust-boundary notes are in [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md).
172
+
173
+ ## Repository Map
174
+
175
+ | Path | Purpose |
176
+ |---|---|
177
+ | `src/oath/receipt/` | `Notarized<T>` envelope, canonicalization, signatures, prompt hashing |
178
+ | `src/oath/mcp/` | Typed forensic tool surface and evidence-handle plumbing |
179
+ | `src/oath/witness/` | Verifier, claim predicates, self-correction events |
180
+ | `src/oath/benchmark/` | DFIR-Metric harness and scoring utilities |
181
+ | `tests/integration/test_spoliation.py` | Spoliation, data-integrity, chain, and Daubert-binding tests |
182
+ | `logs/self-correction-demo/` | Re-runnable self-correction artifact |
183
+ | `web/` | Static receipt explorer for signed sample envelopes |
184
+
185
+ ## What OATH Does Not Claim
186
+
187
+ OATH does not prove legal admissibility, certify tool correctness, make wrappers
188
+ honest by magic, prove general DFIR competence, or remove the need for examiner
189
+ review. It provides a concrete receipt and verifier pattern for making
190
+ LLM-assisted forensic claims auditable.
191
+
192
+ ## Documentation
193
+
194
+ - [Architecture](docs/ARCHITECTURE.md)
195
+ - [Artifact release notes](docs/ARTIFACT.md)
196
+ - [Publication and citation notes](docs/PUBLICATION.md)
197
+ - [Accuracy and benchmark notes](docs/ACCURACY.md)
198
+ - [Dataset documentation](docs/DATASETS.md)
199
+ - [Try-it-out instructions](docs/TRY_IT_OUT.md)
200
+
201
+ ## License
202
+
203
+ MIT. See [LICENSE](LICENSE).
File without changes
@@ -0,0 +1,42 @@
1
+ # OATH — Eric Zimmerman's tools (EZ tools) in a pinned .NET 9 container.
2
+ #
3
+ # Pins:
4
+ # - .NET 9.0.0 (SDK runtime — EZ tools target net9.0)
5
+ # - dotnet-tools.json controls which tools + which versions get installed.
6
+ #
7
+ # Tools available after build (invoke as `dotnet TOOLNAME` inside the container):
8
+ # - MFTECmd — $MFT, $J ($UsnJrnl), $LogFile, $Boot, $SDS, $I30 parser
9
+ # - EvtxECmd — Windows Event Log (.evtx) parser with Sigma-style maps
10
+ # - AmcacheParser — Amcache.hve parser
11
+ # - PECmd — Prefetch parser
12
+ # - SrumECmd — SRUDB.dat (process / network / energy) parser
13
+ # - WxTCmd — Windows Timeline ActivitiesCache.db parser
14
+ # - RECmd — Registry hive parser with batch-mode plugins
15
+ # - SBECmd — ShellBags parser
16
+ # - JLECmd — Jump List parser
17
+ # - LECmd — LNK (shortcut) parser
18
+ #
19
+ # All tools accept `--csv-output` or `--json-output` for structured output that
20
+ # the OATH typed-functions layer can deterministically re-derive against.
21
+
22
+ FROM mcr.microsoft.com/dotnet/sdk:9.0
23
+
24
+ # Working dir for tool execution. Mounts inbound: /evidence (RO), /output (RW).
25
+ WORKDIR /work
26
+ VOLUME ["/evidence", "/output"]
27
+
28
+ # Install EZ tools via dotnet-tools.json manifest (pinned versions).
29
+ COPY dotnet-tools.json /work/.config/dotnet-tools.json
30
+ RUN cd /work && dotnet tool restore && dotnet tool list
31
+
32
+ # Add the local tool manifest dir to PATH so `EvtxECmd` etc. are callable.
33
+ ENV PATH="/root/.dotnet/tools:${PATH}"
34
+ ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
35
+ ENV DOTNET_NOLOGO=1
36
+
37
+ # Quick self-check — fails the build if any tool was misnamed or unreleased.
38
+ RUN dotnet EvtxECmd --version || (echo "EvtxECmd not found" && exit 1)
39
+ RUN dotnet MFTECmd --version || (echo "MFTECmd not found" && exit 1)
40
+
41
+ # Idle entrypoint; the OATH MCP server `docker exec`s into this container.
42
+ CMD ["tail", "-f", "/dev/null"]