{"id":51111352,"url":"https://github.com/solomonneas/vervet","last_synced_at":"2026-06-24T18:00:50.066Z","repository":{"id":336925949,"uuid":"1150751092","full_name":"solomonneas/vervet","owner":"solomonneas","description":"Network threat hunting for Zeek and Suricata logs. Explainable per-host risk scoring with evidence chains and MITRE ATT\u0026CK mapping. Reads your logs, never touches your network.","archived":false,"fork":false,"pushed_at":"2026-06-21T07:00:19.000Z","size":2548,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-21T09:00:24.894Z","etag":null,"topics":["blue-team","cybersecurity","detection-engineering","ids","mitre-attack","network-security","python","security-tools","suricata","threat-hunting","zeek"],"latest_commit_sha":null,"homepage":"https://vervet.dev","language":"TypeScript","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/solomonneas.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"solomonneas","ko_fi":"solomonneas","buy_me_a_coffee":"solomonneas"}},"created_at":"2026-02-05T16:41:44.000Z","updated_at":"2026-06-21T07:00:23.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/solomonneas/vervet","commit_stats":null,"previous_names":["solomonneas/bro-hunter","solomonneas/vervet"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/solomonneas/vervet","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solomonneas%2Fvervet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solomonneas%2Fvervet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solomonneas%2Fvervet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solomonneas%2Fvervet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/solomonneas","download_url":"https://codeload.github.com/solomonneas/vervet/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solomonneas%2Fvervet/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34743465,"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-24T02:00:07.484Z","response_time":106,"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":["blue-team","cybersecurity","detection-engineering","ids","mitre-attack","network-security","python","security-tools","suricata","threat-hunting","zeek"],"created_at":"2026-06-24T18:00:49.261Z","updated_at":"2026-06-24T18:00:50.041Z","avatar_url":"https://github.com/solomonneas.png","language":"TypeScript","funding_links":["https://github.com/sponsors/solomonneas","https://ko-fi.com/solomonneas","https://buymeacoffee.com/solomonneas"],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/assets/vervet-banner.jpg\" alt=\"Vervet network threat hunting banner\"\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eVervet\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003eVervet reads your Zeek and Suricata logs and tells you which hosts are compromised and why.\u003c/strong\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/solomonneas/vervet/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://github.com/solomonneas/vervet/actions/workflows/ci.yml/badge.svg\" alt=\"CI\"\u003e\u003c/a\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Python-3.11%2B-3776AB?logo=python\u0026logoColor=white\" alt=\"Python 3.11+\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/React-18-61DAFB?logo=react\u0026logoColor=0f172a\" alt=\"React 18\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/MITRE_ATT%26CK-mapped-f97316\" alt=\"MITRE ATT\u0026CK mapped\"\u003e\n  \u003ca href=\"LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-Apache--2.0-blue\" alt=\"Apache-2.0\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://solomonneas.dev/projects/vervet\"\u003e\u003cimg src=\"https://img.shields.io/badge/Portfolio-solomonneas.dev-22c55e\" alt=\"Portfolio\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\nPoint Vervet at a directory of Zeek and Suricata logs and it surfaces the threats hiding in them: C2 beacons phoning home on a fixed interval, DNS tunneling and DGA domains, data exfiltration, lateral movement, and long-lived connections that shouldn't exist. Every flagged host gets a transparent risk score with the **evidence chain that produced it** and the **MITRE ATT\u0026CK techniques** it maps to, so an analyst sees not just *what* fired but *why*. It runs as a single container on your own hardware. No cloud, no telemetry, no live tap required, and it never touches your network, it only reads logs you already collect.\n\nVervet is for blue teams, SOC analysts, and MSSPs who run Zeek or Suricata and want the analyst layer that hunts the logs for them, the way RITA and AC-Hunter do for beaconing, but UI-first, MITRE-mapped, and speaking both sensors.\n\n\u003cp align=\"center\"\u003e\n  \u003cstrong\u003e▶ Try the live demo: \u003ca href=\"https://demo.vervet.dev\"\u003edemo.vervet.dev\u003c/a\u003e\u003c/strong\u003e\u003cbr\u003e\n  \u003csub\u003eNo install. Real (sanitized) traffic with a C2 beacon and DNS tunnel already detected.\u003c/sub\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/assets/screenshots/beacons.png\" alt=\"Vervet beacon analysis: scatter plot of score vs interval with per-beacon detail\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/assets/screenshots/threats.png\" width=\"49%\" alt=\"Per-host threat scoring mapped to MITRE ATT\u0026CK by tactic\"\u003e\n  \u003cimg src=\"docs/assets/screenshots/dashboard.png\" width=\"49%\" alt=\"SOC dashboard overview\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\u003csub\u003eDemo data: real Zeek logs (sanitized) with a synthetic C2 beacon and DNS-tunnel scenario layered in. Every address is an RFC 5737 / RFC 2544 documentation range.\u003c/sub\u003e\u003c/p\u003e\n\n## Try it with zero logs of your own\n\nDemo mode loads a realistic sample environment (beaconing C2, DNS tunneling, a noisy Suricata sensor) so the dashboard shows scored, explained threats immediately:\n\n```bash\ngit clone https://github.com/solomonneas/vervet.git\ncd vervet\ndocker compose up -d --build\n# open http://localhost:8000\n```\n\nThe container serves the API and the web UI on the same port and seeds the demo data on startup. Stop it with `docker compose down`.\n\n## Run it on your own logs\n\n```bash\n# Point it at your Zeek/Suricata log directory instead of the demo data\ndocker compose run --rm -e VERVET_DEMO_MODE=false \\\n  -v /var/log/zeek:/logs:ro vervet\n```\n\nThen upload or ingest logs from the UI, or via the REST API:\n\n```bash\n# Zeek conn/dns/http/ssl logs and Suricata eve.json are all accepted\ncurl -X POST http://localhost:8000/api/v1/ingest/directory \\\n  -H \"X-API-Key: $VERVET_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"path\": \"/logs\"}'\n```\n\n### Without Docker (development)\n\n```bash\n# Backend (FastAPI) on :8000\npip install -r requirements.txt\nVERVET_DEMO_MODE=true uvicorn api.main:app --host 0.0.0.0 --port 8000\n\n# Frontend (Vite dev server) on :5174, in another terminal\nnpm install \u0026\u0026 npm run dev\n```\n\n`make dev` starts both at once. See the [Makefile](Makefile) for individual targets.\n\n## What it detects\n\n| Detection | What it finds | Maps to |\n| --- | --- | --- |\n| **Beaconing / C2** | Periodic callbacks by interval regularity, jitter, and data-size consistency | T1071, T1571 |\n| **DNS tunneling** | High-entropy subdomains and oversized TXT/NULL records used as a covert channel | T1071.004, T1048 |\n| **DGA domains** | Algorithmically generated domains via n-gram and lexical analysis | T1568.002 |\n| **Fast-flux** | Domains rotating through many IPs to hide infrastructure | T1568 |\n| **Lateral movement** | Internal-to-internal connection patterns that suggest pivoting | T1021 |\n| **Long connections** | Unusually persistent flows by duration, protocol, and direction | T1071, T1572 |\n| **Suricata alerts** | Severity-weighted IDS alerts folded into the same per-host score | varies |\n\nEach detection contributes to a **unified per-host risk score (0-100)** with a full reasoning chain. Scoring is deterministic and explainable, not a black box: you can read exactly which signals raised a host's score and by how much.\n\n## How it works\n\n```\nZeek logs (conn/dns/http/ssl/x509/notice)   Suricata eve.json\n                 \\                                  /\n                  +--\u003e unified parsers -------------+\n                                |\n                  detection engines (beacon, DNS threat,\n                  lateral movement, long-conn, Suricata)\n                                |\n                  unified threat engine -\u003e per-host score\n                  + MITRE ATT\u0026CK mapping + evidence chain\n                                |\n         web UI + REST API  \u003c---+---\u003e case management / IOC export\n                                       (TheHive / Wazuh / MISP)\n```\n\nLogs are parsed into a common connection/event model, run through each detection engine, and aggregated by the unified threat engine into per-host scores with MITRE mappings and evidence chains. Findings can be promoted to cases, exported as IOCs, and pushed to TheHive, correlated against Wazuh, or enriched from MISP.\n\n\u003e **Note on persistence (current limitation):** the OSS edition keeps its analysis index **in memory**. It is built for log-batch hunting and triage sessions, not yet as a long-running system of record. Restarting clears loaded logs and analysis (cases, hunt notes, and trends are file-backed). A durable store is the top roadmap item, see below.\n\n## Integrations\n\nInitial endpoints exist for exporting cases to **TheHive**, correlating IOCs against **Wazuh** alerts, and enriching IOCs from **MISP**. Configure via environment variables (`THEHIVE_URL`/`THEHIVE_API_KEY`, `WAZUH_URL`/`WAZUH_API_KEY`, `MISP_URL`/`MISP_API_KEY`) and drive from `/api/v1/integrations/*`.\n\n## Security model\n\n- **Read-only on the wire.** Vervet ingests logs you already collect. There is no code path that talks to a network device or captures live traffic.\n- **API-key auth.** Set `VERVET_API_KEY` to require a key on every request. Without it, the server runs in open dev mode and says so loudly at startup.\n- **Ingestion sandbox.** Set `VERVET_LOG_ROOT` to restrict directory ingestion to a single tree, so the API can't be coaxed into reading arbitrary paths.\n- **Upload rate limiting.** PCAP/upload endpoints are rate-limited by default (`VERVET_RATE_LIMIT_*`) to protect public deployments.\n- **Local data, no telemetry.** Everything stays in your data directory. No external calls except the integrations you configure.\n\n## Roadmap\n\n- **Durable persistence** (SQLite-backed index, audit trail) so investigations survive restarts, the prerequisite for team use.\n- **Live log tailing** for near-real-time dashboards instead of batch ingest.\n- **Multi-sensor** support and alert suppression / noise controls.\n- **MCP server** so agents can query hunts directly.\n\n## License\n\nApache-2.0. See [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsolomonneas%2Fvervet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsolomonneas%2Fvervet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsolomonneas%2Fvervet/lists"}