What happened?
src/matcher/matchers.ts:37, 44 treats inputs that exceed MAX_MATCH_INPUT_LENGTH as a match (return true). The function's docstring claims this is "fail-closed", but in practice it fires the first matching rule's action.
If a rule pack has an allow rule ordered before the relevant block rule, an oversized input passes through. The fail-closed guarantee is only as strong as the first matching rule in the pack — a rule-author or rule-ordering mistake silently turns this into a fail-open path.
What did you expect to happen?
An oversized input should not be matched against any rule. Either:
- the matcher returns
false (no match) so the engine can take a dedicated path that always returns block regardless of rule order, or
- the engine has a dedicated "oversized input" branch that always returns
block before rules are evaluated.
Steps to reproduce
- Define a rule pack with an
allow: { pattern: ".*" } rule ordered first, then a block rule
- Call the engine with a
command of length > MAX_MATCH_INPUT_LENGTH
- Observe the call is allowed because the
allow rule "matched" via the length short-circuit
What happened?
src/matcher/matchers.ts:37, 44treats inputs that exceedMAX_MATCH_INPUT_LENGTHas a match (return true). The function's docstring claims this is "fail-closed", but in practice it fires the first matching rule's action.If a rule pack has an
allowrule ordered before the relevantblockrule, an oversized input passes through. The fail-closed guarantee is only as strong as the first matching rule in the pack — a rule-author or rule-ordering mistake silently turns this into a fail-open path.What did you expect to happen?
An oversized input should not be matched against any rule. Either:
false(no match) so the engine can take a dedicated path that always returnsblockregardless of rule order, orblockbefore rules are evaluated.Steps to reproduce
allow: { pattern: ".*" }rule ordered first, then ablockrulecommandof length> MAX_MATCH_INPUT_LENGTHallowrule "matched" via the length short-circuit