{"id":"GHSA-pcxq-fjp3-r752","summary":"Ash has authorization bypass when bypass policy condition evaluates to true","details":"### Summary\nBypass policies incorrectly authorize requests when their condition evaluates to true but their authorization checks fail and no other policies apply.\n\n### Impact\nResources with bypass policies can be accessed without proper authorization when:\n- Bypass condition evaluates to true\n- Bypass authorization checks fail\n- Other policies exist but their conditions don't match\n\n### Details\nVulnerable code in: [lib/ash/policy/policy.ex:69](https://github.com/ash-project/ash/blob/b2e4d625/lib/ash/policy/policy.ex#L69)\n\n```elixir\n{%{bypass?: true}, cond_expr, complete_expr}, {one_condition_matches, all_policies_match} -\u003e\n  {\n    b(cond_expr or one_condition_matches),  # \u003c- Bug: uses condition only\n    b(complete_expr or all_policies_match)\n  }\n```\n\nThe final authorization decision is: `one_condition_matches AND all_policies_match`\n\nWhen a bypass condition is true but bypass policies fail, and subsequent policies have non-matching conditions:\n\n1. **one_condition_matches** = `cond_expr` (bypass condition) = **true** (bug - should check if bypass actually authorizes)\n2. **all_policies_match** = `(complete_expr OR NOT cond_expr)` for each policy\n   - For non-matching policies: `(false OR NOT false)` = **true** (policies don't apply)\n3. **Final**: `true AND true` = **true** (incorrectly authorized)\n\nThe bypass condition alone satisfies \"at least one policy applies\" even though the bypass fails to authorize.\n\n### Fix\nReplace `cond_expr` with `complete_expr` on line 69:\n```elixir\n{%{bypass?: true}, _cond_expr, complete_expr}, {one_condition_matches, all_policies_match} -\u003e\n  {\n    b(complete_expr or one_condition_matches),  # \u003c- Fixed\n    b(complete_expr or all_policies_match)\n  }\n```\n\nLine 52 should also be updated for consistency (though it's only triggered when bypass is the last policy, making it coincidentally safe in practice):\n```elixir\n{%{bypass?: true}, _cond_expr, complete_expr}, {one_condition_matches, true} -\u003e\n  {\n    b(complete_expr or one_condition_matches),  # \u003c- For consistency\n    complete_expr\n  }\n```\n\n### PoC\n```elixir\npolicies do\n  bypass always() do\n    authorize_if actor_attribute_equals(:is_admin, true)\n  end\n\n  policy action_type(:read) do\n    authorize_if always()\n  end\nend\n```\n\nNon-admin user can perform create actions (should be denied).\n\nTest demonstrating the bug:\n```elixir\ntest \"bypass policy bug\" do\n  policies = [\n    %Ash.Policy.Policy{\n      bypass?: true,\n      condition: [{Ash.Policy.Check.Static, result: true}],  # condition = true\n      policies: [\n        %Ash.Policy.Check{\n          type: :authorize_if,\n          check: {Ash.Policy.Check.Static, result: false},  # policies = false\n          check_module: Ash.Policy.Check.Static,\n          check_opts: [result: false]\n        }\n      ]\n    },\n    %Ash.Policy.Policy{\n      bypass?: false,\n      condition: [{Ash.Policy.Check.Static, result: false}],\n      policies: [\n        %Ash.Policy.Check{\n          type: :authorize_if,\n          check: {Ash.Policy.Check.Static, result: true},\n          check_module: Ash.Policy.Check.Static,\n          check_opts: [result: true]\n        }\n      ]\n    }\n  ]\n\n  expression = Ash.Policy.Policy.expression(policies, %{})\n  \n  assert expression == false\n  # Expected: false (deny)\n  # Actual on main: true (incorrectly authorized)\nend\n```","aliases":["CVE-2025-48044","EEF-CVE-2025-48044"],"modified":"2026-07-08T07:14:05.301169272Z","published":"2025-10-17T18:03:06Z","database_specific":{"github_reviewed_at":"2025-10-17T18:03:06Z","nvd_published_at":"2025-10-17T14:15:46Z","cwe_ids":["CWE-863"],"severity":"HIGH","github_reviewed":true},"references":[{"type":"WEB","url":"https://github.com/ash-project/ash/security/advisories/GHSA-pcxq-fjp3-r752"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2025-48044"},{"type":"WEB","url":"https://github.com/ash-project/ash/commit/8b83efa225f657bfc3656ad8ee8485f9b2de923d"},{"type":"WEB","url":"https://cna.erlef.org/cves/CVE-2025-48044.html"},{"type":"PACKAGE","url":"https://github.com/ash-project/ash"},{"type":"WEB","url":"https://osv.dev/vulnerability/EEF-CVE-2025-48044"}],"affected":[{"package":{"name":"ash","ecosystem":"Hex","purl":"pkg:hex/ash"},"ranges":[{"type":"SEMVER","events":[{"introduced":"3.6.3"},{"fixed":"3.7.1"}]}],"versions":["3.6.3","3.7.0"],"database_specific":{"last_known_affected_version_range":"\u003c= 3.7.0","source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2025/10/GHSA-pcxq-fjp3-r752/GHSA-pcxq-fjp3-r752.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V3","score":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N"},{"type":"CVSS_V4","score":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N"}]}