VYPR
High severityOSV Advisory· Published Oct 17, 2025· Updated Apr 15, 2026

CVE-2025-48044

CVE-2025-48044

Description

Incorrect Authorization vulnerability in ash-project ash allows Authentication Bypass. This vulnerability is associated with program files lib/ash/policy/policy.ex and program routines 'Elixir.Ash.Policy.Policy':expression/2.

This issue affects ash: from pkg:hex/ash@3.6.3 before pkg:hex/ash@3.7.1, from 3.6.3 before 3.7.1, from 79749c2685ea031ebb2de8cf60cc5edced6a8dd0 before 8b83efa225f657bfc3656ad8ee8485f9b2de923d.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
ashHex
>= 3.6.3, < 3.7.13.7.1

Affected products

1

Patches

2
8b83efa225f6

Merge commit from fork

https://github.com/ash-project/ashJechol LeeOct 17, 2025via ghsa
2 files changed · +65 8
  • lib/ash/policy/policy.ex+7 8 modified
    @@ -49,26 +49,25 @@ defmodule Ash.Policy.Policy do
           {policy, cond_expr, complete_expr}
         end)
         |> List.foldr({false, true}, fn
    -      {%{bypass?: true}, cond_expr, complete_expr}, {one_condition_matches, true} ->
    +      {%{bypass?: true}, _cond_expr, complete_expr}, {one_condition_matches, true} ->
             {
    -          b(cond_expr or one_condition_matches),
    -          # Bypass can't relay to the next bypass if there is none
    +          b(complete_expr or one_condition_matches),
               complete_expr
             }
     
           {%FieldPolicy{bypass?: true}, true, complete_expr},
           {one_condition_matches, all_policies_match} ->
             {
    -          # FieldPolicy Conditions are set to true by default and therefore
    -          # have to be ignore to not change the meaning of the
    -          # one_condition_matches condition
               one_condition_matches,
               b(complete_expr or all_policies_match)
             }
     
    -      {%{bypass?: true}, cond_expr, complete_expr}, {one_condition_matches, all_policies_match} ->
    +      {%{bypass?: true}, _cond_expr, complete_expr},
    +      {one_condition_matches, all_policies_match} ->
             {
    -          b(cond_expr or one_condition_matches),
    +          # Bypass should only contribute to "at least one policy applies" if it actually authorizes.
    +          # Use complete_expr (condition AND policies) not just condition.
    +          b(complete_expr or one_condition_matches),
               b(complete_expr or all_policies_match)
             }
     
    
  • test/policy/policy_test.exs+58 0 modified
    @@ -912,4 +912,62 @@ defmodule Ash.Test.Policy.Policy do
                  """
         end
       end
    +
    +  describe "bypass policy with always-true condition" do
    +    test "denies when bypass condition is true but bypass policies fail" do
    +      # Scenario: non-admin user performs create action with these policies:
    +      #
    +      #   bypass always() do
    +      #     authorize_if actor_attribute_equals(:is_admin, true)
    +      #   end
    +      #
    +      #   policy action_type(:read) do
    +      #     authorize_if always()
    +      #   end
    +      #
    +      # Before fix: Used bypass condition (always) for one_condition_matches
    +      #   → one_condition_matches = true (bypass condition matched)
    +      #   → all_policies_match = true (no applicable policy)
    +      #   → Final: true AND true = true (WRONG! - incorrectly authorized)
    +      #
    +      # After fix: Use bypass complete_expr (always AND is_admin) for one_condition_matches
    +      #   → one_condition_matches = false (bypass failed to authorize)
    +      #   → all_policies_match = true (no applicable policy)
    +      #   → Final: false AND true = false (CORRECT! - properly denied)
    +
    +      policies = [
    +        # bypass always(), do: authorize_if(actor_attribute_equals(:is_admin, true))
    +        %Ash.Policy.Policy{
    +          bypass?: true,
    +          condition: [{Ash.Policy.Check.Static, result: true}],
    +          policies: [
    +            %Ash.Policy.Check{
    +              type: :authorize_if,
    +              check: {Ash.Policy.Check.Static, result: false},
    +              check_module: Ash.Policy.Check.Static,
    +              check_opts: [result: false]
    +            }
    +          ]
    +        },
    +        # policy action_type(:read) do: authorize_if(always())
    +        %Ash.Policy.Policy{
    +          bypass?: false,
    +          condition: [{Ash.Policy.Check.Static, result: false}],
    +          policies: [
    +            %Ash.Policy.Check{
    +              type: :authorize_if,
    +              check: {Ash.Policy.Check.Static, result: true},
    +              check_module: Ash.Policy.Check.Static,
    +              check_opts: [result: true]
    +            }
    +          ]
    +        }
    +      ]
    +
    +      expression = Ash.Policy.Policy.expression(policies, %{})
    +
    +      # Should deny: bypass failed and no policy condition matched
    +      assert expression == false
    +    end
    +  end
     end
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.