Emit deny action inline when includeEngineConfig=false - #81
Open
cognitivegears wants to merge 1 commit into
Open
Emit deny action inline when includeEngineConfig=false#81cognitivegears wants to merge 1 commit into
cognitivegears wants to merge 1 commit into
Conversation
Generated rules use the `block` action, which inherits the disruptive action from the SecDefaultAction emitted in mainconfig.conf. With includeEngineConfig=false that SecDefaultAction is omitted, so `block` inherits the host engine's phase-2 default. A host ruleset such as the OWASP Core Rule Set defaults phase 2 to `pass`, so the layered OAShield rules silently no-op: they log but never deny. When includeEngineConfig=false, emit the disruptive action inline on each rule (deny,status:N / drop / pass / redirect, driven by denyAction/denyStatus) via a new `ruleDisruptiveAction` template variable, so the rules block regardless of the host's default action. When the engine config is included (the default), rules keep the bare `block` and output is unchanged, so golden snapshots are unaffected. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019tqxm2rpR6mhJdodg7TbU4
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.
Problem
OAShield's generated rules use the
blockaction, whose disruptive behavior is inherited from theSecDefaultActionemitted inmainconfig.conf. WithincludeEngineConfig=false(the documented way to layer the rules onto an engine that already configures itself), thatSecDefaultActionis omitted — soblockinherits the host engine's phase-2 default.The OWASP Core Rule Set defaults phase 2 to
pass(it uses anomaly scoring with an explicitdenyonly in rule 949110). So when OAShield rules are layered onto a Coraza/ModSecurity + CRS deployment withincludeEngineConfig=false, every OAShield rule silently no-ops: it logs but never denies. A request that violates the API contract (undeclared parameter, shadow endpoint, bad type) is logged and then forwarded to the app.Repro: generate with
includeEngineConfig=false, load the rules into a stock Coraza+CRS reverse proxy, POST a body with an undeclared property → CRS forwards it, and OAShield logsUnknown parameter detectedbut returns 200 instead of 403.Fix
Introduce a
ruleDisruptiveActiontemplate variable:includeEngineConfig=true(default) →block(unchanged; rules inherit the emittedSecDefaultAction).includeEngineConfig=false→ the disruptive action inline (deny,status:N/drop/pass/redirect, driven by the existingdenyAction/denyStatus/denyRedirectUrl), so the rules block regardless of the host's default action — or, withdenyAction=pass, run detection-only.This is the natural meaning of the two options together: if you're not emitting the engine config, the rules can't rely on it, so they carry the action themselves.
Compatibility
Default output is unchanged —
GoldenFileTest(all sample specs × both flavors) passes with no golden churn, becauseruleDisruptiveActionis stillblockwhenever the engine config is emitted.Tests
DenyConfigTestgains three cases (all green,mvn test -Dtest=DenyConfigTest,GoldenFileTest→ 24 run, 0 failures):includeEngineConfig=false→ operation rules and the catch-all default-deny carry inlinedeny,status:403, no bareblock.includeEngineConfig=false+denyAction=pass→ inlinepass(detection-only).blockpreserved.Docs
docs/configuration.mdupdated to describe the inline-action behavior underincludeEngineConfig=false.🤖 Generated with Claude Code