Description
eval_expression uses ? inside And and Or, so an unorderable operand aborts the
expression even when a sibling already settles it. With args.amount = "lots",
args.amount > 10000 | subject.role == "admin": deny denies the phase instead of taking
true from the second operand. The same happens on & when one operand is definitely
false.
The result is order dependent: a | b and b | a decide differently when one side is
unknown. Not a fail-open, it errs the other way, but a policy language should not depend
on operand order.
Depends on the Result<bool, Unorderable> plumbing that lands with #45.
Measured
On security/analysis-pass at 8855038, with args.amount = "lots" and
subject.role = "admin":
| Rule |
Decision |
args.amount > 10000 & subject.role == "guest": deny |
Deny, unorderable |
subject.role == "guest" & args.amount > 10000: deny |
Allow |
args.amount > 10000 | subject.role == "admin": deny |
Deny, unorderable |
subject.role == "admin" | args.amount > 10000: deny |
Deny, rule fired |
The first pair is the same policy with the operands swapped and it decides differently.
The second pair both deny, but only one names the rule, so the audit reason changes with
operand order too.
Acceptance criteria
| returns true if any operand is true, & returns false if any operand is false,
regardless of an unorderable sibling.
- Unorderable is returned only when no operand settles the expression.
- Tests cover both orders of
unknown | true and unknown & false.
- CHANGELOG entry: some phases that denied on an unparseable value now evaluate normally.
Description
eval_expressionuses?insideAndandOr, so an unorderable operand aborts theexpression even when a sibling already settles it. With
args.amount = "lots",args.amount > 10000 | subject.role == "admin": denydenies the phase instead of takingtruefrom the second operand. The same happens on&when one operand is definitelyfalse.
The result is order dependent:
a | bandb | adecide differently when one side isunknown. Not a fail-open, it errs the other way, but a policy language should not depend
on operand order.
Depends on the
Result<bool, Unorderable>plumbing that lands with #45.Measured
On
security/analysis-passat8855038, withargs.amount = "lots"andsubject.role = "admin":args.amount > 10000 & subject.role == "guest": denysubject.role == "guest" & args.amount > 10000: denyargs.amount > 10000 | subject.role == "admin": denysubject.role == "admin" | args.amount > 10000: denyThe first pair is the same policy with the operands swapped and it decides differently.
The second pair both deny, but only one names the rule, so the audit reason changes with
operand order too.
Acceptance criteria
|returns true if any operand is true,&returns false if any operand is false,regardless of an unorderable sibling.
unknown | trueandunknown & false.