fix(waf): push rule suppressions to nodes as SecRuleRemoveById - #15
Merged
Merged
Conversation
Suppressing a rule in Admin -> Security -> WAF only hid its events; in blocking mode the node kept answering 403. Active suppressions (global and per-route) are now appended to every WAF-enabled route's directives after the CRS include, and saving or deleting one re-pushes all nodes. Rule IDs are whitelisted (NNN or NNN-MMM) before they reach SecLang since the form stores free text. Root cause of the report: not SSE. Beszel's dashboard opens /api/realtime fine, then POSTs subscription topics like "systems/*"; CRS 942100 (libinjection) reads "/*" as a SQL comment, the anomaly score hits the threshold and the POST gets 403, so the SDK reconnects forever. Verified in headless Chrome against a local Beszel hub behind caddy+coraza v2.5.0: blocking mode fails, blocking mode + SecRuleRemoveById 942100 passes. Documented in docs/WAF.md. Fixes #14
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #14
Root cause
The report describes a hung EventSource, but the SSE stream itself is fine. Reproduced with a local Beszel 0.19.0 hub behind
caddy:2.11.4+coraza-caddy v2.5.0(same pins as the edge image), driven by headless Chrome:GET /api/realtime200, subscriptionPOST /api/realtime204GET200,POST403, console:Failed to subscribe to systems collection: ClientResponseError 403The POST body carries PocketBase subscription topics like
systems/*?options=.... CRS942100(libinjection SQLi) treats/*as a SQL comment, the anomaly score reaches the blocking threshold, and the SDK reconnects forever, which looks like a stuck EventSource. Plain"systems"passes,"systems/*"is blocked.Fix
The panel already had a "suppress rule" UI, but it only hid events - it never reached the node config, so in blocking mode the rule kept firing.
internal/domain/routes/waf_suppress.go: active suppressions (global + per-route) are rendered asSecRuleRemoveById <id>and appended to every WAF-enabled route's directives, after the CRS include (whereSecRuleRemoveByIdmust sit, see [WAF] Custom instructions not seems to be applied #9).NNNorNNN-MMM) before reaching SecLang - the form stores free text.docs/WAF.mdgets a "Blocking mode and JSON API false positives" section with the Beszel/PocketBase case and the manual directive.Verification
go test ./internal/domain/routes/ ./internal/caddyapi/ ./internal/wafevents/ ./internal/httpserver/...green; new unit test covers global/per-route scoping, dedupe, ranges, and an injection attempt (942100; SecRuleEngine Offis dropped).SecRuleRemoveById 942100in the generated directives:GET200,POST204, 204, no console errors.