jtshor14899/threat-dash
GitHub: jtshor14899/threat-dash
Stars: 0 | Forks: 0
# threat-dash
[](./LICENSE)
[](./Dockerfile)
[](./Dockerfile)
[](./Dockerfile)
[](https://github.com/jtshor14899/threat-dash/issues)
[](https://github.com/jtshor14899/threat-dash/stargazers)
`, `/host/search` |
Anything you don't have a key for is hidden in the UI with a tooltip
explaining why. Threat-dash always degrades gracefully — you can run with
just Cloudflare + DB-IP and still get a useful dashboard.
## REST + SSE endpoints
The UI is a thin client over a small REST API:
GET /api/stats?range=24h&self=hide&direction=in|out
GET /api/arcs?range=24h&limit=400
GET /api/events?range=24h&limit=200
GET /api/intel/outbound?range=24h&limit=250
GET /api/signins?range=24h
GET /api/containers?container=&range=24h
GET /api/blocks
POST /api/block {ip, mode?, reason?, expires_at?}
DEL /api/blocks/
PATCH /api/blocks/ {mode?, reason?, expires_at?}
GET /api/recon/status
GET /api/shodan/surface?base=
GET /api/shodan/drill?base=&category=
GET /api/shodan/host/
GET /api/censys/host/
GET /api/recon/search?q=&per_page=25
GET /api/greynoise/
GET /api/vt/{ip,domain,hash,url}/
POST /api/scan {ip, profile=common|extended, force?}
GET /stream Server-Sent Events
GET /healthz 200 ok (used by HEALTHCHECK)
Useful for scripting threat-dash into bigger SOAR-y workflows — e.g. block a
list of IPs from a Slack slash-command.
## Performance
The frontend is opinionated about not melting your browser:
- SSE events are batched on a 200 ms rAF tick (no per-event re-renders).
- Globe redraws throttled to ~3 fps regardless of feed velocity.
- `renderStats` short-circuits when the data signature is unchanged.
- Periodic refresh slows to 2 min when `document.hidden`.
- All list updates use `DocumentFragment` + `replaceChildren`.
The Python server:
- One process, threaded `HTTPServer`. SSE clients each get a bounded
`queue.Queue` so a slow consumer can't back up the broadcast.
- SQLite WAL with a single `threading.Lock` for writes; reads are
unsynchronised.
- Outbound enrichment is rate-limited to 5 IPs/tick (every 60 s) so the
free-tier API quotas can't be blown by a sudden burst of new
destinations.
On a modest VM (2 vCPU / 2 GB) with ~60 k events/day, RSS sits around 80 MB.
## Security
Threat-dash is a security tool. It deserves a high bar.
- **Never expose port 5959 publicly without auth in front.** There is no
user model. Anyone with the URL can block IPs at your Cloudflare edge.
- Runs as **non-root** (UID 1000) in a multi-stage image with all Linux
capabilities dropped and `no-new-privileges:true`.
- `HEALTHCHECK` on `/healthz` so orchestrators notice when it's wedged.
- Outbound TCP scanner is **operator-triggered**, connect+banner only — no
exploitation paths. Confirm scanning is OK in your jurisdiction.
- `.env` is git-ignored; rotate the Cloudflare token quarterly.
Full threat model + hardening checklist in
[`docs/SECURITY-HARDENING.md`](./docs/SECURITY-HARDENING.md).
Reporting a vulnerability: [`SECURITY.md`](./SECURITY.md).
## Roadmap
- [ ] Built-in basic-auth / proxy-header auth for users not fronting with
their own proxy
- [ ] Saved query bundles ("weekly region attack-surface diff")
- [ ] ntfy / Slack / Discord webhook on threat-score thresholds
- [ ] Cross-reference outbound CVEs with Trivy SBOM scans of your images
- [ ] Image published to GHCR for pull-not-build deploys
- [ ] More providers: AbuseIPDB, AlienVault OTX, IPinfo Lite
Open an issue if you want to vote one up or propose a different one.
## License
[MIT](./LICENSE). The runtime DB-IP Lite databases are CC-BY 4.0 by
[db-ip.com](https://db-ip.com).
Built for homelab operators by a homelab operator. If this saved you
from getting credential-stuffed by a botnet, [⭐ star the repo][stars] —
that's the only marketing budget we have.
(Run scripts/seed-demo-data.py to populate a copy with realistic synthetic data — see SCREENSHOTS.md.)





