Policy Refactoring#2365
Merged
Merged
Conversation
Changing the order of statements can have a performance impact. eg. (var and expensive()) will check expensive() only if var is true. If it were reversed, the expensive() check would always be run.
Allows to execute a callback on each node in the given boolean expression to replace the current node. Has a variant with and without an accumulator.
Takes a boolean expression and performs logical constant folding and simplification by removing redundant negations, constants, and tautologies.
Will walk the expression and apply the callback to expand nodes. It will constantly optimize the expression itself to avoid expansion where logical constant folding does no longer require a value.
Allows direct access to the internally used expression
Remove conditions to check which policies might apply and track the decision in the expression instead.
All done in expand_constant instead
All besides true / false are done in simplify_policy_expression
zachdaniel
reviewed
Oct 10, 2025
zachdaniel
approved these changes
Oct 10, 2025
Contributor
|
🚀 Thank you for your contribution! 🚀 |
jechol
added a commit
to jechol/ash
that referenced
this pull request
Oct 17, 2025
The Policy Refactoring (ash-project#2365) introduced a bug where bypass policies were contributing only their condition to one_condition_matches instead of their complete expression (condition AND policies). This caused bypass policies with always-true conditions (like always()) to incorrectly satisfy the "at least one policy applies" requirement even when the bypass policies themselves failed. For example, with these policies: - bypass always() do authorize_if actor_attribute_equals(:is_admin, true) - policy action_type(:read) do authorize_if always() A non-admin user performing a create action would be incorrectly authorized because: 1. bypass condition (always) was true → one_condition_matches = true 2. policy condition (action_type(:read)) was false 3. Final: true AND (tautology) = true (incorrect!) The fix restores the old behavior where bypass policies contribute their complete expression to one_condition_matches, ensuring that a bypass only satisfies the requirement if it actually authorizes. Fixes authorization bypass when bypass conditions are always true but bypass policies fail.
jechol
added a commit
to jechol/ash
that referenced
this pull request
Oct 17, 2025
The Policy Refactoring (ash-project#2365) introduced a bug where bypass policies were contributing only their condition to one_condition_matches instead of their complete expression (condition AND policies). This caused bypass policies with always-true conditions (like always()) to incorrectly satisfy the "at least one policy applies" requirement even when the bypass policies themselves failed. For example, with these policies: - bypass always() do authorize_if actor_attribute_equals(:is_admin, true) - policy action_type(:read) do authorize_if always() A non-admin user performing a create action would be incorrectly authorized because: 1. bypass condition (always) was true → one_condition_matches = true 2. policy condition (action_type(:read)) was false 3. Final: true AND (tautology) = true (incorrect!) The fix restores the old behavior where bypass policies contribute their complete expression to one_condition_matches, ensuring that a bypass only satisfies the requirement if it actually authorizes. Fixes authorization bypass when bypass conditions are always true but bypass policies fail.
jechol
added a commit
to jechol/ash
that referenced
this pull request
Oct 17, 2025
The Policy Refactoring (ash-project#2365) introduced a bug where bypass policies were contributing only their condition to one_condition_matches instead of their complete expression (condition AND policies). This caused bypass policies with always-true conditions (like always()) to incorrectly satisfy the "at least one policy applies" requirement even when the bypass policies themselves failed. For example, with these policies: - bypass always() do authorize_if actor_attribute_equals(:is_admin, true) - policy action_type(:read) do authorize_if always() A non-admin user performing a create action would be incorrectly authorized because: 1. bypass condition (always) was true → one_condition_matches = true 2. policy condition (action_type(:read)) was false 3. Final: true AND (tautology) = true (incorrect!) The fix restores the old behavior where bypass policies contribute their complete expression to one_condition_matches, ensuring that a bypass only satisfies the requirement if it actually authorizes. Fixes authorization bypass when bypass conditions are always true but bypass policies fail.
jechol
added a commit
to jechol/ash
that referenced
this pull request
Oct 17, 2025
The Policy Refactoring (ash-project#2365) introduced a bug where bypass policies were contributing only their condition to one_condition_matches instead of their complete expression (condition AND policies). This caused bypass policies with always-true conditions (like always()) to incorrectly satisfy the "at least one policy applies" requirement even when the bypass policies themselves failed. For example, with these policies: - bypass always() do authorize_if actor_attribute_equals(:is_admin, true) - policy action_type(:read) do authorize_if always() A non-admin user performing a create action would be incorrectly authorized because: 1. bypass condition (always) was true → one_condition_matches = true 2. policy condition (action_type(:read)) was false 3. Final: true AND (tautology) = true (incorrect!) The fix restores the old behavior where bypass policies contribute their complete expression to one_condition_matches, ensuring that a bypass only satisfies the requirement if it actually authorizes. Fixes authorization bypass when bypass conditions are always true but bypass policies fail.
jechol
added a commit
to jechol/ash
that referenced
this pull request
Oct 17, 2025
The Policy Refactoring (ash-project#2365) introduced a bug where bypass policies were contributing only their condition to one_condition_matches instead of their complete expression (condition AND policies). This caused bypass policies with always-true conditions (like always()) to incorrectly satisfy the "at least one policy applies" requirement even when the bypass policies themselves failed. For example, with these policies: - bypass always() do authorize_if actor_attribute_equals(:is_admin, true) - policy action_type(:read) do authorize_if always() A non-admin user performing a create action would be incorrectly authorized because: 1. bypass condition (always) was true → one_condition_matches = true 2. policy condition (action_type(:read)) was false 3. Final: true AND (tautology) = true (incorrect!) The fix restores the old behavior where bypass policies contribute their complete expression to one_condition_matches, ensuring that a bypass only satisfies the requirement if it actually authorizes. Fixes authorization bypass when bypass conditions are always true but bypass policies fail.
jechol
added a commit
to jechol/ash
that referenced
this pull request
Oct 17, 2025
The Policy Refactoring (ash-project#2365) introduced a bug where bypass policies were contributing only their condition to one_condition_matches instead of their complete expression (condition AND policies). This caused bypass policies with always-true conditions (like always()) to incorrectly satisfy the "at least one policy applies" requirement even when the bypass policies themselves failed. For example, with these policies: - bypass always() do authorize_if actor_attribute_equals(:is_admin, true) - policy action_type(:read) do authorize_if always() A non-admin user performing a create action would be incorrectly authorized because: 1. bypass condition (always) was true → one_condition_matches = true 2. policy condition (action_type(:read)) was false 3. Final: true AND (tautology) = true (incorrect!) The fix restores the old behavior where bypass policies contribute their complete expression to one_condition_matches, ensuring that a bypass only satisfies the requirement if it actually authorizes. Fixes authorization bypass when bypass conditions are always true but bypass policies fail.
jechol
added a commit
to jechol/ash
that referenced
this pull request
Oct 17, 2025
The Policy Refactoring (ash-project#2365) introduced a bug where bypass policies were contributing only their condition to one_condition_matches instead of their complete expression (condition AND policies). This caused bypass policies with always-true conditions (like always()) to incorrectly satisfy the "at least one policy applies" requirement even when the bypass policies themselves failed. For example, with these policies: - bypass always() do authorize_if actor_attribute_equals(:is_admin, true) - policy action_type(:read) do authorize_if always() A non-admin user performing a create action would be incorrectly authorized because: 1. bypass condition (always) was true → one_condition_matches = true 2. policy condition (action_type(:read)) was false 3. Final: true AND (tautology) = true (incorrect!) The fix restores the old behavior where bypass policies contribute their complete expression to one_condition_matches, ensuring that a bypass only satisfies the requirement if it actually authorizes. Fixes authorization bypass when bypass conditions are always true but bypass policies fail.
jechol
added a commit
to jechol/ash
that referenced
this pull request
Oct 17, 2025
The Policy Refactoring (ash-project#2365) introduced a bug where bypass policies were contributing only their condition to one_condition_matches instead of their complete expression (condition AND policies). This caused bypass policies with always-true conditions (like always()) to incorrectly satisfy the "at least one policy applies" requirement even when the bypass policies themselves failed. For example, with these policies: - bypass always() do authorize_if actor_attribute_equals(:is_admin, true) - policy action_type(:read) do authorize_if always() A non-admin user performing a create action would be incorrectly authorized because: 1. bypass condition (always) was true → one_condition_matches = true 2. policy condition (action_type(:read)) was false 3. Final: true AND (tautology) = true (incorrect!) The fix restores the old behavior where bypass policies contribute their complete expression to one_condition_matches, ensuring that a bypass only satisfies the requirement if it actually authorizes. Fixes authorization bypass when bypass conditions are always true but bypass policies fail.
jechol
added a commit
to jechol/ash
that referenced
this pull request
Oct 17, 2025
The Policy Refactoring (ash-project#2365) introduced a bug where bypass policies were contributing only their condition to one_condition_matches instead of their complete expression (condition AND policies). This caused bypass policies with always-true conditions (like always()) to incorrectly satisfy the "at least one policy applies" requirement even when the bypass policies themselves failed. For example, with these policies: - bypass always() do authorize_if actor_attribute_equals(:is_admin, true) - policy action_type(:read) do authorize_if always() A non-admin user performing a create action would be incorrectly authorized because: 1. bypass condition (always) was true → one_condition_matches = true 2. policy condition (action_type(:read)) was false 3. Final: true AND (tautology) = true (incorrect!) The fix restores the old behavior where bypass policies contribute their complete expression to one_condition_matches, ensuring that a bypass only satisfies the requirement if it actually authorizes. Fixes authorization bypass when bypass conditions are always true but bypass policies fail.
jechol
added a commit
to jechol/ash
that referenced
this pull request
Oct 17, 2025
The Policy Refactoring (ash-project#2365) introduced a bug where bypass policies were contributing only their condition to one_condition_matches instead of their complete expression (condition AND policies). This caused bypass policies with always-true conditions (like always()) to incorrectly satisfy the "at least one policy applies" requirement even when the bypass policies themselves failed. For example, with these policies: - bypass always() do authorize_if actor_attribute_equals(:is_admin, true) - policy action_type(:read) do authorize_if always() A non-admin user performing a create action would be incorrectly authorized because: 1. bypass condition (always) was true → one_condition_matches = true 2. policy condition (action_type(:read)) was false 3. Final: true AND (tautology) = true (incorrect!) The fix restores the old behavior where bypass policies contribute their complete expression to one_condition_matches, ensuring that a bypass only satisfies the requirement if it actually authorizes. Fixes authorization bypass when bypass conditions are always true but bypass policies fail.
jechol
added a commit
to jechol/ash
that referenced
this pull request
Oct 17, 2025
The Policy Refactoring (ash-project#2365) introduced a bug where bypass policies were contributing only their condition to one_condition_matches instead of their complete expression (condition AND policies). This caused bypass policies with always-true conditions (like always()) to incorrectly satisfy the "at least one policy applies" requirement even when the bypass policies themselves failed. For example, with these policies: - bypass always() do authorize_if actor_attribute_equals(:is_admin, true) - policy action_type(:read) do authorize_if always() A non-admin user performing a create action would be incorrectly authorized because: 1. bypass condition (always) was true → one_condition_matches = true 2. policy condition (action_type(:read)) was false 3. Final: true AND (tautology) = true (incorrect!) The fix restores the old behavior where bypass policies contribute their complete expression to one_condition_matches, ensuring that a bypass only satisfies the requirement if it actually authorizes. Fixes authorization bypass when bypass conditions are always true but bypass policies fail.
jechol
added a commit
to jechol/ash
that referenced
this pull request
Oct 17, 2025
The Policy Refactoring (ash-project#2365) introduced a bug where bypass policies were contributing only their condition to one_condition_matches instead of their complete expression (condition AND policies). This caused bypass policies with always-true conditions (like always()) to incorrectly satisfy the "at least one policy applies" requirement even when the bypass policies themselves failed. For example, with these policies: - bypass always() do authorize_if actor_attribute_equals(:is_admin, true) - policy action_type(:read) do authorize_if always() A non-admin user performing a create action would be incorrectly authorized because: 1. bypass condition (always) was true → one_condition_matches = true 2. policy condition (action_type(:read)) was false 3. Final: true AND (tautology) = true (incorrect!) The fix restores the old behavior where bypass policies contribute their complete expression to one_condition_matches, ensuring that a bypass only satisfies the requirement if it actually authorizes. Fixes authorization bypass when bypass conditions are always true but bypass policies fail.
jechol
added a commit
to jechol/ash
that referenced
this pull request
Oct 17, 2025
The Policy Refactoring (ash-project#2365) introduced a bug where bypass policies were contributing only their condition to one_condition_matches instead of their complete expression (condition AND policies). This caused bypass policies with always-true conditions (like always()) to incorrectly satisfy the "at least one policy applies" requirement even when the bypass policies themselves failed. For example, with these policies: - bypass always() do authorize_if actor_attribute_equals(:is_admin, true) - policy action_type(:read) do authorize_if always() A non-admin user performing a create action would be incorrectly authorized because: 1. bypass condition (always) was true → one_condition_matches = true 2. policy condition (action_type(:read)) was false 3. Final: true AND (tautology) = true (incorrect!) The fix restores the old behavior where bypass policies contribute their complete expression to one_condition_matches, ensuring that a bypass only satisfies the requirement if it actually authorizes. Fixes authorization bypass when bypass conditions are always true but bypass policies fail.
jechol
added a commit
to jechol/ash
that referenced
this pull request
Oct 17, 2025
The Policy Refactoring (ash-project#2365) introduced a bug where bypass policies were contributing only their condition to one_condition_matches instead of their complete expression (condition AND policies). This caused bypass policies with always-true conditions (like always()) to incorrectly satisfy the "at least one policy applies" requirement even when the bypass policies themselves failed. For example, with these policies: - bypass always() do authorize_if actor_attribute_equals(:is_admin, true) - policy action_type(:read) do authorize_if always() A non-admin user performing a create action would be incorrectly authorized because: 1. bypass condition (always) was true → one_condition_matches = true 2. policy condition (action_type(:read)) was false 3. Final: true AND (tautology) = true (incorrect!) The fix restores the old behavior where bypass policies contribute their complete expression to one_condition_matches, ensuring that a bypass only satisfies the requirement if it actually authorizes. Fixes authorization bypass when bypass conditions are always true but bypass policies fail.
jechol
added a commit
to jechol/ash
that referenced
this pull request
Oct 17, 2025
The Policy Refactoring (ash-project#2365) introduced a bug where bypass policies were contributing only their condition to one_condition_matches instead of their complete expression (condition AND policies). This caused bypass policies with always-true conditions (like always()) to incorrectly satisfy the "at least one policy applies" requirement even when the bypass policies themselves failed. For example, with these policies: - bypass always() do authorize_if actor_attribute_equals(:is_admin, true) - policy action_type(:read) do authorize_if always() A non-admin user performing a create action would be incorrectly authorized because: 1. bypass condition (always) was true → one_condition_matches = true 2. policy condition (action_type(:read)) was false 3. Final: true AND (tautology) = true (incorrect!) The fix restores the old behavior where bypass policies contribute their complete expression to one_condition_matches, ensuring that a bypass only satisfies the requirement if it actually authorizes. Fixes authorization bypass when bypass conditions are always true but bypass policies fail.
jechol
added a commit
to jechol/ash
that referenced
this pull request
Oct 17, 2025
The Policy Refactoring (ash-project#2365) introduced a bug where bypass policies were contributing only their condition to one_condition_matches instead of their complete expression (condition AND policies). This caused bypass policies with always-true conditions (like always()) to incorrectly satisfy the "at least one policy applies" requirement even when the bypass policies themselves failed. For example, with these policies: - bypass always() do authorize_if actor_attribute_equals(:is_admin, true) - policy action_type(:read) do authorize_if always() A non-admin user performing a create action would be incorrectly authorized because: 1. bypass condition (always) was true → one_condition_matches = true 2. policy condition (action_type(:read)) was false 3. Final: true AND (tautology) = true (incorrect!) The fix restores the old behavior where bypass policies contribute their complete expression to one_condition_matches, ensuring that a bypass only satisfies the requirement if it actually authorizes. Fixes authorization bypass when bypass conditions are always true but bypass policies fail.
jechol
added a commit
to jechol/ash
that referenced
this pull request
Oct 17, 2025
The Policy Refactoring (ash-project#2365) introduced a bug where bypass policies were contributing only their condition to one_condition_matches instead of their complete expression (condition AND policies). This caused bypass policies with always-true conditions (like always()) to incorrectly satisfy the "at least one policy applies" requirement even when the bypass policies themselves failed. For example, with these policies: - bypass always() do authorize_if actor_attribute_equals(:is_admin, true) - policy action_type(:read) do authorize_if always() A non-admin user performing a create action would be incorrectly authorized because: 1. bypass condition (always) was true → one_condition_matches = true 2. policy condition (action_type(:read)) was false 3. Final: true AND (tautology) = true (incorrect!) The fix restores the old behavior where bypass policies contribute their complete expression to one_condition_matches, ensuring that a bypass only satisfies the requirement if it actually authorizes. Fixes authorization bypass when bypass conditions are always true but bypass policies fail.
jechol
added a commit
to jechol/ash
that referenced
this pull request
Oct 17, 2025
The Policy Refactoring (ash-project#2365) introduced a bug where bypass policies were contributing only their condition to one_condition_matches instead of their complete expression (condition AND policies). This caused bypass policies with always-true conditions (like always()) to incorrectly satisfy the "at least one policy applies" requirement even when the bypass policies themselves failed. For example, with these policies: - bypass always() do authorize_if actor_attribute_equals(:is_admin, true) - policy action_type(:read) do authorize_if always() A non-admin user performing a create action would be incorrectly authorized because: 1. bypass condition (always) was true → one_condition_matches = true 2. policy condition (action_type(:read)) was false 3. Final: true AND (tautology) = true (incorrect!) The fix restores the old behavior where bypass policies contribute their complete expression to one_condition_matches, ensuring that a bypass only satisfies the requirement if it actually authorizes. Fixes authorization bypass when bypass conditions are always true but bypass policies fail.
jechol
added a commit
to jechol/ash
that referenced
this pull request
Oct 17, 2025
The Policy Refactoring (ash-project#2365) introduced a bug where bypass policies were contributing only their condition to one_condition_matches instead of their complete expression (condition AND policies). This caused bypass policies with always-true conditions (like always()) to incorrectly satisfy the "at least one policy applies" requirement even when the bypass policies themselves failed. For example, with these policies: - bypass always() do authorize_if actor_attribute_equals(:is_admin, true) - policy action_type(:read) do authorize_if always() A non-admin user performing a create action would be incorrectly authorized because: 1. bypass condition (always) was true → one_condition_matches = true 2. policy condition (action_type(:read)) was false 3. Final: true AND (tautology) = true (incorrect!) The fix restores the old behavior where bypass policies contribute their complete expression to one_condition_matches, ensuring that a bypass only satisfies the requirement if it actually authorizes. Fixes authorization bypass when bypass conditions are always true but bypass policies fail.
jechol
added a commit
to jechol/ash
that referenced
this pull request
Oct 17, 2025
Add failing test that shows bypass policies with always-true conditions incorrectly authorize when bypass policies fail. This test currently FAILS with: left: true (incorrectly authorized) right: false (expected) The bug is fixed in PR #3.
jechol
added a commit
to jechol/ash
that referenced
this pull request
Oct 17, 2025
The Policy Refactoring (ash-project#2365) introduced a bug where bypass policies were contributing only their condition to one_condition_matches instead of their complete expression (condition AND policies). This caused bypass policies with always-true conditions (like always()) to incorrectly satisfy the "at least one policy applies" requirement even when the bypass policies themselves failed. For example, with these policies: - bypass always() do authorize_if actor_attribute_equals(:is_admin, true) - policy action_type(:read) do authorize_if always() A non-admin user performing a create action would be incorrectly authorized because: 1. bypass condition (always) was true → one_condition_matches = true 2. policy condition (action_type(:read)) was false 3. Final: true AND (tautology) = true (incorrect!) The fix restores the old behavior where bypass policies contribute their complete expression to one_condition_matches, ensuring that a bypass only satisfies the requirement if it actually authorizes. Fixes authorization bypass when bypass conditions are always true but bypass policies fail.
jechol
added a commit
to jechol/ash
that referenced
this pull request
Oct 17, 2025
The Policy Refactoring (ash-project#2365) introduced a bug where bypass policies were contributing only their condition to one_condition_matches instead of their complete expression (condition AND policies). This caused bypass policies with always-true conditions (like always()) to incorrectly satisfy the "at least one policy applies" requirement even when the bypass policies themselves failed. For example, with these policies: - bypass always() do authorize_if actor_attribute_equals(:is_admin, true) - policy action_type(:read) do authorize_if always() A non-admin user performing a create action would be incorrectly authorized because: 1. bypass condition (always) was true → one_condition_matches = true 2. policy condition (action_type(:read)) was false 3. Final: true AND (tautology) = true (incorrect!) The fix restores the old behavior where bypass policies contribute their complete expression to one_condition_matches, ensuring that a bypass only satisfies the requirement if it actually authorizes. Fixes authorization bypass when bypass conditions are always true but bypass policies fail.
jechol
added a commit
to jechol/ash
that referenced
this pull request
Oct 17, 2025
The Policy Refactoring (ash-project#2365) introduced a bug where bypass policies were contributing only their condition to one_condition_matches instead of their complete expression (condition AND policies). This caused bypass policies to incorrectly satisfy the "at least one policy applies" requirement when their condition evaluates to true but their authorization checks fail. For example, with these policies: - bypass always() do authorize_if actor_attribute_equals(:is_admin, true) - policy action_type(:read) do authorize_if always() A non-admin user performing a create action would be incorrectly authorized because: 1. bypass condition evaluates to true -> one_condition_matches = true 2. bypass policies fail (user is not admin) 3. policy condition doesn't match (create is not read) 4. Final: true AND true = true (incorrect!) The fix ensures bypass policies contribute their complete expression to one_condition_matches, so a bypass only satisfies the requirement if it actually authorizes.
jechol
added a commit
to jechol/ash
that referenced
this pull request
Oct 17, 2025
The Policy Refactoring (ash-project#2365) introduced a bug where bypass policies were contributing only their condition to one_condition_matches instead of their complete expression (condition AND policies). This caused bypass policies to incorrectly satisfy the "at least one policy applies" requirement when their condition evaluates to true but their authorization checks fail. For example, with these policies: - bypass always() do authorize_if actor_attribute_equals(:is_admin, true) - policy action_type(:read) do authorize_if always() A non-admin user performing a create action would be incorrectly authorized because: 1. bypass condition evaluates to true -> one_condition_matches = true 2. bypass policies fail (user is not admin) 3. policy condition doesn't match (create is not read) 4. Final: true AND true = true (incorrect!) The fix ensures bypass policies contribute their complete expression to one_condition_matches, so a bypass only satisfies the requirement if it actually authorizes.
jechol
added a commit
to jechol/ash
that referenced
this pull request
Oct 17, 2025
The Policy Refactoring (ash-project#2365) introduced a bug where bypass policies were contributing only their condition to one_condition_matches instead of their complete expression (condition AND policies). This caused bypass policies to incorrectly satisfy the "at least one policy applies" requirement when their condition evaluates to true but their authorization checks fail. For example, with these policies: bypass always(), do: authorize_if(actor_attribute_equals(:is_admin, true)) policy action_type(:read), do: authorize_if(always()) A non-admin user performing a create action would be incorrectly authorized because: 1. bypass condition evaluates to true -> one_condition_matches = true 2. bypass policies fail (user is not admin) 3. policy condition doesn't match (create is not read) 4. Final: true AND true = true (incorrect!) The fix ensures bypass policies contribute their complete expression to one_condition_matches, so a bypass only satisfies the requirement if it actually authorizes.
jechol
added a commit
to jechol/ash
that referenced
this pull request
Oct 17, 2025
The Policy Refactoring (ash-project#2365) introduced a bug where bypass policies were contributing only their condition to one_condition_matches instead of their complete expression (condition AND policies). This caused bypass policies to incorrectly satisfy the "at least one policy applies" requirement when their condition evaluates to true but their authorization checks fail. For example, with these policies: bypass always(), do: authorize_if(actor_attribute_equals(:is_admin, true)) policy action_type(:read), do: authorize_if(always()) A non-admin user performing a create action would be incorrectly authorized because: 1. bypass condition evaluates to true -> one_condition_matches = true 2. bypass policies fail (user is not admin) 3. policy condition doesn't match (create is not read) 4. all_policies_match remains true (non-matching policies don't apply) 5. Final: one_condition_matches AND all_policies_match = true AND true = true The fix ensures bypass policies contribute their complete expression to one_condition_matches, so a bypass only satisfies the requirement if it actually authorizes.
jechol
added a commit
to jechol/ash
that referenced
this pull request
Oct 17, 2025
The Policy Refactoring (ash-project#2365) introduced a bug where bypass policies were contributing only their condition to one_condition_matches instead of their complete expression (condition AND policies). This caused bypass policies to incorrectly satisfy the "at least one policy applies" requirement when their condition evaluates to true but their authorization checks fail. For example, with these policies: bypass always(), do: authorize_if(actor_attribute_equals(:is_admin, true)) policy action_type(:read), do: authorize_if(always()) The final authorization decision is: one_condition_matches AND all_policies_match When a bypass condition is true but bypass policies fail, and subsequent policies have non-matching conditions: 1. one_condition_matches = cond_expr (bypass condition) = true (bug - should check if bypass actually authorizes) 2. all_policies_match = (complete_expr OR NOT cond_expr) for each policy - For non-matching policies: (false OR NOT false) = true (policies don't apply) 3. Final: true AND true = true (incorrectly authorized) The bypass condition alone satisfies "at least one policy applies" even though the bypass fails to authorize. The fix ensures bypass policies contribute their complete expression (condition AND policies) to one_condition_matches.
zachdaniel
pushed a commit
that referenced
this pull request
Oct 17, 2025
The Policy Refactoring (#2365) introduced a bug where bypass policies were contributing only their condition to one_condition_matches instead of their complete expression (condition AND policies). This caused bypass policies to incorrectly satisfy the "at least one policy applies" requirement when their condition evaluates to true but their authorization checks fail. For example, with these policies: bypass always(), do: authorize_if(actor_attribute_equals(:is_admin, true)) policy action_type(:read), do: authorize_if(always()) The final authorization decision is: one_condition_matches AND all_policies_match When a bypass condition is true but bypass policies fail, and subsequent policies have non-matching conditions: 1. one_condition_matches = cond_expr (bypass condition) = true (bug - should check if bypass actually authorizes) 2. all_policies_match = (complete_expr OR NOT cond_expr) for each policy - For non-matching policies: (false OR NOT false) = true (policies don't apply) 3. Final: true AND true = true (incorrectly authorized) The bypass condition alone satisfies "at least one policy applies" even though the bypass fails to authorize. The fix ensures bypass policies contribute their complete expression (condition AND policies) to one_condition_matches.
jechol
added a commit
to jechol/ash
that referenced
this pull request
Oct 18, 2025
The Policy Refactoring (ash-project#2365) introduced a bug in Checker.strict_check_all_facts where policy checks were evaluated even when the policy condition was false. For example, with this policy: policy action_type([:create, :update]) do authorize_if AshStateMachine.Checks.ValidNextState end When a read action was performed: 1. The action_type condition was evaluated and set to false in facts 2. But strict_check_all_policies was called unconditionally 3. ValidNextState.filter/3 was called with a query context (no changeset) 4. This caused FunctionClauseError since filter/3 only handles changeset contexts The fix checks if any condition is false before evaluating policy checks. Since policy conditions are ANDed together, one false condition means the policy doesn't apply regardless of its checks. This improves both correctness and performance by avoiding unnecessary check evaluations when policies don't apply.
jechol
added a commit
to jechol/ash
that referenced
this pull request
Oct 18, 2025
The Policy Refactoring (ash-project#2365) introduced a bug where ActionType checks were not evaluated during the simplification phase, even when the action was known. This caused unnecessary evaluation of policy checks when the action type didn't match. For example, with this policy: policy action_type([:create, :update]) do authorize_if AshStateMachine.Checks.ValidNextState end When a read action was performed: 1. ActionType.simplify didn't evaluate to false (action was not in context) 2. Expression remained: action_type([:create, :update]) and ValidNextState 3. expand_constants tried to evaluate ValidNextState 4. ValidNextState.filter/3 was called with query context (no changeset) 5. FunctionClauseError - filter/3 only handles changeset contexts Solutions: 1. Modified check_context to include action in the context 2. Modified ActionType.simplify to evaluate immediately when action is available, returning true/false instead of check reference This enables proper short-circuit evaluation: - Read action: action_type([:create, :update]) → false - Expression: false and ValidNextState → false (ValidNextState not evaluated) - Avoids crashes and improves performance
jechol
added a commit
to jechol/ash
that referenced
this pull request
Oct 18, 2025
The Policy Refactoring (ash-project#2365) introduced a bug where ActionType checks were not evaluated during the simplification phase, even when the action was known. This caused unnecessary evaluation of policy checks when the action type didn't match. For example, with this policy: policy action_type([:create, :update]) do authorize_if AshStateMachine.Checks.ValidNextState end When a read action was performed: 1. ActionType.simplify didn't evaluate to false (action was not in context) 2. Expression remained: action_type([:create, :update]) and ValidNextState 3. expand_constants tried to evaluate ValidNextState 4. ValidNextState.filter/3 was called with query context (no changeset) 5. FunctionClauseError - filter/3 only handles changeset contexts Solutions: 1. Modified check_context to include action in the context 2. Modified ActionType.simplify to evaluate immediately when action is available, returning true/false instead of check reference This enables proper short-circuit evaluation: - Read action: action_type([:create, :update]) → false - Expression: false and ValidNextState → false (ValidNextState not evaluated) - Avoids crashes and improves performance
jechol
added a commit
to jechol/ash
that referenced
this pull request
Oct 18, 2025
The Policy Refactoring (ash-project#2365) introduced a bug where ActionType checks were not evaluated during the simplification phase, even when the action was known. This caused unnecessary evaluation of policy checks when the action type didn't match. For example, with this policy: policy action_type([:create, :update]) do authorize_if AshStateMachine.Checks.ValidNextState end When a read action was performed: 1. ActionType.simplify didn't evaluate to false (action was not in context) 2. Expression remained: action_type([:create, :update]) and ValidNextState 3. expand_constants tried to evaluate ValidNextState 4. ValidNextState.filter/3 was called with query context (no changeset) 5. FunctionClauseError - filter/3 only handles changeset contexts Solutions: 1. Modified check_context to include action in the context 2. Modified ActionType.simplify to evaluate immediately when action is available, returning true/false instead of check reference This enables proper short-circuit evaluation: - Read action: action_type([:create, :update]) → false - Expression: false and ValidNextState → false (ValidNextState not evaluated) - Avoids crashes and improves performance
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.
Contributor checklist
Leave anything that you believe does not apply unchecked.