{"id":50927878,"url":"https://github.com/manojmallick/find-evil","last_synced_at":"2026-06-17T01:03:49.187Z","repository":{"id":365104920,"uuid":"1270573742","full_name":"manojmallick/find-evil","owner":"manojmallick","description":"Autonomous, audit-traced incident-response agent for the SANS SIFT Workstation. The agent has no shell — evidence tampering and hallucinated findings are architecturally impossible. Every finding verifies in \u003c10s via its call_id. SANS Find Evil! Hackathon 2026.","archived":false,"fork":false,"pushed_at":"2026-06-15T22:41:55.000Z","size":4633,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-15T23:18:06.387Z","etag":null,"topics":["ai-agent","anthropic","audit-trail","claude","cybersecurity","dfir","digital-forensics","forensics","hackathon","incident-response","llm","mcp","memory-forensics","model-context-protocol","python","sans-sift","volatility","yara"],"latest_commit_sha":null,"homepage":"https://findevil.devpost.com","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/manojmallick.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-15T21:07:30.000Z","updated_at":"2026-06-15T22:47:39.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/manojmallick/find-evil","commit_stats":null,"previous_names":["manojmallick/find-evil"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/manojmallick/find-evil","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/manojmallick%2Ffind-evil","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/manojmallick%2Ffind-evil/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/manojmallick%2Ffind-evil/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/manojmallick%2Ffind-evil/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/manojmallick","download_url":"https://codeload.github.com/manojmallick/find-evil/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/manojmallick%2Ffind-evil/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34429497,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-16T02:00:06.860Z","response_time":126,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agent","anthropic","audit-trail","claude","cybersecurity","dfir","digital-forensics","forensics","hackathon","incident-response","llm","mcp","memory-forensics","model-context-protocol","python","sans-sift","volatility","yara"],"created_at":"2026-06-17T01:03:48.286Z","updated_at":"2026-06-17T01:03:49.174Z","avatar_url":"https://github.com/manojmallick.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Find Evil! 🔍\n\n![Find Evil! — autonomous, audit-traced IR for the SIFT Workstation](assets/cover.png)\n\n**Autonomous, audit-traced incident response for the SANS SIFT Workstation.**\n\n\u003e AI-powered adversaries operate in minutes; human responders are still pulling\n\u003e up their toolkit. Find Evil! is an autonomous IR agent that analyzes disk and\n\u003e memory evidence the way a senior analyst does — sequencing tools, recognizing\n\u003e anomalies, and self-correcting — while making **evidence tampering and\n\u003e hallucinated findings architecturally impossible**, not merely discouraged.\n\nBuilt for the **SANS Find Evil! Hackathon 2026**. Apache 2.0.\n\n---\n\n## Why this is different\n\nMost \"AI for DFIR\" demos give a model a shell and a polite instruction not to\nbreak things. Find Evil! removes the shell. The agent reaches the OS **only**\nthrough a custom MCP server exposing typed forensic tools — `rm`, `dd`, `curl`,\n`ssh` do not exist in its world.\n\n| Property | How it's guaranteed | Proof |\n|---|---|---|\n| **Evidence can't be tampered** | `rm`/`dd`/`shred`/redirects to `/cases`,`/mnt` rejected in code before any subprocess spawns | `tests/unit/test_guardrails.py` (30 tests), `BYPASS_TESTING.md` (12/12) |\n| **No exfiltration** | `curl`/`wget`/`ssh`/`scp`/`nc` not in the tool surface; blocked at `_safe_run` | same |\n| **0% hallucination (CONFIRMED tier)** | every CONFIRMED finding must carry a `call_id` present in the audit log, or the report refuses to generate | `tests/unit/test_report_integrity.py`, `ACCURACY_REPORT.md` |\n| **Full chain of custody** | every tool call → UUID `call_id` + SHA256 of output in `tool_calls.jsonl`; any finding greps back in \u003c10s | `DEMO_VIDEO_SCRIPT.md` Shot 6 |\n\nThese map directly to the hackathon's judging criteria: **Constraint\nImplementation (architectural vs prompt-based)** and **Audit Trail Quality**.\n\n---\n\n## Architecture (30-second version)\n\n```\nAgent (6-phase loop)  ──calls──►  MCP server (typed tools only)  ──guarded──►  SIFT binaries\n   │                                  │  rm/dd/curl DO NOT EXIST here          (log2timeline, vol, ...)\n   │                                  ▼\n   └──────────────────────────►  Audit log (tool_calls.jsonl: call_id + SHA256)\n                                      │\n   Report generator  ◄──verifies every CONFIRMED call_id against the log──┘\n```\n\nFull diagram with trust boundaries: **[ARCHITECTURE.md](ARCHITECTURE.md)**.\n\n---\n\n## Quick start (SIFT Workstation, Ubuntu 22.04)\n\n```bash\n# One-command install (clones, venv, deps, YARA rules, directories, shell wrapper)\ncurl -fsSL https://raw.githubusercontent.com/manojmallick/find-evil/main/install.sh | bash\n```\n\nOr from source:\n\n```bash\ngit clone https://github.com/manojmallick/find-evil.git\ncd find-evil\npython3 -m venv .venv \u0026\u0026 source .venv/bin/activate\npip install -e \".[dev]\"\n```\n\n### Run an analysis\n\n```bash\n# 1. Mount evidence read-only\nsudo ewfmount /path/to/evidence.E01 /mnt/ewf/\nsudo mount -o ro,loop,noatime /mnt/ewf/ewf1 /mnt/case_disk\n\n# 2. Create a case\nmkdir -p /cases/CASE001\ncp /cases/TEMPLATE/CLAUDE.md /cases/CASE001/\n\n# 3. Analyze (disk + memory)\nfind-evil --case /cases/CASE001 --disk /mnt/case_disk \\\n          --memory /cases/CASE001/memory.raw --max-iterations 3\n\n# 4. View + verify\npython3 -m json.tool /cases/CASE001/findings/findings.json\nfirefox /cases/CASE001/findings/report.html\ngrep '\u003ccall_id from report\u003e' /opt/find-evil/logs/tool_calls.jsonl | python3 -m json.tool\n```\n\n---\n\n## Two execution modes\n\n**Deterministic pipeline (default)** — a fixed, reproducible 6-phase sequence.\nCourt-defensible: the same case always runs the same way.\n\n**Autonomous reasoning (`--reasoning`)** — a Claude model drives the\ninvestigation: it chooses the next tool based on what it finds, narrates its\nanalyst reasoning, forms and tests hypotheses, and self-corrects. **The\narchitectural guarantees still hold while the LLM is in control** — it can only\ncall the typed tools (no `rm`/`curl`), and a CONFIRMED finding it records is\nrejected unless its `call_id` is in the audit log. Full autonomy, zero loss of\nevidence integrity. Requires `ANTHROPIC_API_KEY`; falls back to deterministic.\n\n```bash\nfind-evil --case /cases/CASE001 --disk /mnt/case_disk --reasoning   # autonomous\n```\n\n## The 6-phase analysis pipeline\n\n1. **Triage** — chain-of-custody hash + YARA IOC sweep (20 custom rules)\n2. **Timeline** — MFT + prefetch + **timestomping detection ($SI vs $FN)**\n3. **Memory** — Volatility **pslist + malfind (injected code) + netscan**\n4. **Artifacts** — registry persistence + logon event logs\n5. **Correlation** — cross-source discrepancy detection + bounded self-correction\n6. **Report** — verify every `call_id`, render `findings.json` + `report.html`\n\nThe self-correction loop is the demo's centerpiece: a process in the disk\nprefetch timeline but absent from the memory process list is flagged, three\nhypotheses are formed, and targeted re-analysis runs — autonomously.\n\n**10 typed forensic tools**, covering disk, memory, registry, event logs, YARA,\nanti-forensics (timestomping), and memory injection/network analysis.\n\n---\n\n## Verify the guarantees yourself (no SIFT needed)\n\n```bash\npython3 -m pytest tests/                                   # 56 passed\npython3 tests/benchmark/run_benchmark.py --dataset synthetic   # precision/recall + 0% hallucination\n```\n\n- **56 tests** lock in the guardrails, the audit trail, and the hallucination guarantee.\n- The **synthetic benchmark** runs anywhere and asserts 0% CONFIRMED-tier hallucination.\n\n---\n\n## Repository layout\n\n```\nmcp_server/      Custom MCP server — typed forensic tools + architectural guardrails\n  config.py        BLOCKED_COMMANDS, PROTECTED_WRITE_PATHS, path/injection validation\n  safe_exec.py     _safe_run() — the single guarded, shell=False chokepoint\n  logger.py        Audit trail (tool_calls.jsonl) + SHA256 evidence integrity\n  tools.py         10 typed forensic tools (rm/dd/curl deliberately absent)\n  server.py        FastMCP registration layer\nagent/loop.py    The `find-evil` command — 6-phase orchestrator + self-correction\n  reasoning.py   Autonomous LLM mode (--reasoning) — Claude drives tool selection\nreports/         Findings model + report generator (enforces call_id integrity)\ntests/           56 unit/integration tests + reproducible benchmark harness\nfind_evil_custom.yar   20 custom YARA rules (lateral movement, persistence, C2, ...)\ninstall.sh       One-command SIFT installer\n```\n\n---\n\n## Documentation\n\n| Doc | What |\n|---|---|\n| [ARCHITECTURE.md](ARCHITECTURE.md) | Layered architecture + security/trust boundaries |\n| [BYPASS_TESTING.md](BYPASS_TESTING.md) | 12 documented bypass attempts, all blocked |\n| [ACCURACY_REPORT.md](ACCURACY_REPORT.md) | Precision/recall, false positives, hallucination analysis |\n| [DATASETS.md](DATASETS.md) | Test datasets + how ground truth is established |\n| [DEMO_VIDEO_SCRIPT.md](DEMO_VIDEO_SCRIPT.md) | 5-minute demo shot list |\n| [DEVPOST.md](DEVPOST.md) | Project description (Devpost submission text) |\n\n---\n\n## License\n\nApache 2.0 — see [LICENSE](LICENSE). Evidence integrity is the product.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmanojmallick%2Ffind-evil","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmanojmallick%2Ffind-evil","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmanojmallick%2Ffind-evil/lists"}