You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
identity/boolpolicy: parser depth cap doesn't bound the evaluator, and evaluation isn't memoized #2077
The boolpolicy parser's maxParseDepth limits how deeply nested parentheses can be, but the AST
evaluator that walks the parsed policy has no equivalent bound, and evaluation isn't memoized. A
policy string that stays within the parser's depth limit and length limit can still produce a large,
repetitive AST that causes the evaluator to repeat the same verification work many times over.
Where
token/services/identity/boolpolicy/parser.go:38 sets maxParseDepth = 64, incremented only when
entering a parenthesized group (parser.go:259-265). parseOr/parseAnd build their chains
iteratively, so a policy like $0 OR $0 OR ... OR $0 — well within maxPolicyLen (4 KiB) — produces
a long, flat-but-large AST without ever tripping the depth counter.
sig.go:91-110evalNode walks that AST and, for each RefNode occurrence, calls v.Verifiers[i].Verify again — so a policy referencing the same signature index many times causes
that verification to run many times, even though the signature itself only needs to be checked once. parser.go:66-82String() recurses over the same AST shape.
Impact
Because the parser's depth bound doesn't constrain how large or repetitive the resulting AST can be,
a policy that's well-formed and within the configured size limit can still cause a disproportionate
amount of cryptographic verification work relative to its size, on the identity-matching path. This
is a resource-usage concern rather than a crash, and is worth addressing with either memoization or
an explicit bound on total AST node count / reference count.
Suggested fix
Add a cap on the total number of nodes (or RefNode occurrences) produced during parsing, alongside
the existing depth cap, so the AST size itself is bounded regardless of shape. Separately, memoizing evalNode's per-index verification result within a single Verify call (a signature at a given
index is being checked against the same data regardless of how many times it's referenced in the
policy) would remove the redundant work without needing to change the AST structure at all.
Severity
MEDIUM-HIGH — bounded by the existing 4 KiB policy-length limit, but the per-length cost is higher
than intended given the parser's depth cap doesn't constrain it.
Activity