selfhostedops-stack/crowdsec/appsec-rules/crs-route-exclusions.yaml
Maximilian Grimm 26a7da0495 Episode 13: tune the OWASP CRS with per-route exclusions
Measured follow-up to the AppSec section. Virtual patching blocks 7 of 41
probes with near-zero false positives; the OWASP CRS raises that to 27 of 41
but, at default paranoia, blocks six legitimate workflows (git push, Forgejo
issues and file contents, Outline documents, ntfy publish, n8n webhooks).

crowdsec/appsec-rules/crs-route-exclusions.yaml disables the SecLang/Coraza
engine (ctl:ruleEngine=Off) for exactly those application routes, matched by
host + URI, so virtual patching still runs there. crowdsec/appsec-configs/
appsec-tuned.yaml wires it in before the CRS rule. Measured with tuning: zero
false positives, still 27 of 41 blocked on non-excluded routes, about +2 ms
per request, ~15-40 MB more RAM.

Trap: RemoveInBandRuleByName in a pre_eval hook does not disable CRS (it is
SecLang, not a native rule); ctl:ruleEngine in phase 1 is the working lever,
and the exclusion rule must be listed before the CRS rule.

The stack runs vpatch+generic by default (zero false positives, no per-app
tuning). The CRS recipe ships as a documented opt-in in crowdsec/README.md.
2026-09-16 20:46:16 +02:00

26 lines
1.6 KiB
YAML

name: selfhostedops/crs-route-exclusions
# ep13: schaltet die CRS-Coraza-Engine (SecLang) fuer genau die legitimen
# Anwendungs-Routen ab, auf denen CRS sonst Fehlalarme wirft. ctl:ruleEngine=Off
# betrifft nur die SecLang-Regeln (CRS + base-config), die nativen vpatch- und
# generic-Regeln von CrowdSec laufen weiter, auch auf diesen Routen.
seclang_rules:
# Forgejo git smart-HTTP (clone/push), binaerer Pack-Body
- |
SecRule REQUEST_HEADERS:Host "@beginsWith git." "id:900101,phase:1,pass,nolog,chain,msg:'ep13 exclude git smart-http'"
SecRule REQUEST_URI "@rx (git-upload-pack|git-receive-pack|/info/refs\?service=)" "ctl:ruleEngine=Off"
# Forgejo REST-API: Issues, Datei-Inhalte (Nutzer schreiben Code/SQL/.env)
- |
SecRule REQUEST_HEADERS:Host "@beginsWith git." "id:900102,phase:1,pass,nolog,chain,msg:'ep13 exclude forgejo api'"
SecRule REQUEST_URI "@beginsWith /api/v1/" "ctl:ruleEngine=Off"
# Outline Dokument-API (Codebloecke)
- |
SecRule REQUEST_HEADERS:Host "@beginsWith wiki." "id:900103,phase:1,pass,nolog,chain,msg:'ep13 exclude outline api'"
SecRule REQUEST_URI "@beginsWith /api/" "ctl:ruleEngine=Off"
# ntfy Publish (POST /<topic>, freier Text)
- |
SecRule REQUEST_HEADERS:Host "@beginsWith ntfy." "id:900104,phase:1,pass,nolog,chain,msg:'ep13 exclude ntfy publish'"
SecRule REQUEST_METHOD "@streq POST" "ctl:ruleEngine=Off"
# n8n Webhook-Pfade (beliebiges JSON)
- |
SecRule REQUEST_HEADERS:Host "@beginsWith n8n." "id:900105,phase:1,pass,nolog,chain,msg:'ep13 exclude n8n webhook'"
SecRule REQUEST_URI "@beginsWith /webhook" "ctl:ruleEngine=Off"