v0.7.4 · updated · GitHub

Threat Engine

26 categories, dual-pass evasion resistance, MITRE-tagged. This page is the honest overview — what is detected, what is not, and where to read the details.

What it does NOT do — limits and false positives

Credibility comes from declaring limits. Read this before trusting a report.

LimitWhyWhat to do
Pattern-based, not semanticLooks for known payload substrings, does not execute codeReview grouped IPs — do not auto-block on low confidence
Confidence filterDefault --detect-confidence 8 in guard; some hits are 5–6Raise to 9 for noisier apps; 0 disables only pattern-based blocks, not guard itself
Legitimate paths can look malicious?url=https://…, ?code={{var}}, __proto__ in docsUse --never-block / whitelist and check -f html before blocking
Behavioral heuristics need stateua_rotation, object_enumeration, beaconing need ≥10 samples per IP/pathRun on ≥1h of traffic; single-request logs will not fire them
Not a WAFOffline/log-time detection, not inline request blockingUse guard to block after detection; do not expect pre-request deny
GeoIP/blocklist are best-effortDB-IP lite + 8 feeds, 7d cache, network required for refreshPin --geoip-db and check blocklist list age
Do not lock yourself out
Every guard example that modifies firewall is marked modifies firewall. On a remote host, always --never-block YOUR_IP. When in doubt, use read-only commands (blocklist list, --detect -f html) first.

What it does

  • Dual-pass engine — every URI is checked raw and URL-unescaped (split ? + PathUnescape/QueryUnescape + manual % fallback) to catch %2e%2e and double-encode bypass. Guard runs the same Detector per window.
  • 26 categories — from sql_injection to beaconing, each tagged with verified MITRE ATT&CK IDs.
  • Grouped by IP — suspicious report shows top IPs with confidence, URI, and techniques.
  • Exportable — 23 pattern categories as Sigma rules; 3 behavioral (ua_rotation, object_enumeration, beaconing) are stateful and not exported.

Where to go next

Quick check

caddy-analyze --detect testdata/sample.log
# should list 26 categories firing (68 lines, all TEST-NET)
caddy-analyze --detect -f html -o report.html testdata/large.log && open report.html
caddy-analyze tail docker://caddy --detect  # live, severity-colored