{"id":"CVE-2025-48044","aliases":["EEF-CVE-2025-48044","EUVD-2025-34884","GHSA-pcxq-fjp3-r752"],"status":"published","title":"Authorization bypass when bypass policy condition evaluates to true","description":"Incorrect Authorization vulnerability in ash-project ash allows Authentication Bypass.\n\nThis issue affects ash: from 3.6.3 before 3.7.1.","severity":{"version":"4.0","score":8.6,"vector":"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","level":"high","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-09","score":0.00679,"percentile":0.52611,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-863"],"published":"2025-10-17T13:52:53Z","modified":"2026-10-28T02:30:24Z","fixes":[{"ecosystem":"Hex","package":"ash","fixed_in":["3.7.1"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"Hex","package":"ash","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.6.3"},{"last_affected":"3.7.0"},{"fixed":"3.7.1"}]}]},{"source":"osv","ecosystem":"Hex","package":"ash","ranges":[{"type":"SEMVER","events":[{"introduced":"3.6.3"},{"fixed":"3.7.1"}]}],"versions":["3.6.3","3.7.0"]},{"source":"osv","ecosystem":"Hex","package":"ash","ranges":[{"type":"SEMVER","events":[{"introduced":"3.6.3"},{"fixed":"3.7.1"}]}],"versions":["3.6.3","3.7.0"]}],"products":[{"vendor":"ash-project","product":"ash"}],"references":[{"url":"https://github.com/ash-project/ash/security/advisories/GHSA-pcxq-fjp3-r752","tags":["related","vendor-advisory","exploit","advisory","web"]},{"url":"https://cna.erlef.org/cves/CVE-2025-48044.html","tags":["related","web"]},{"url":"https://osv.dev/vulnerability/EEF-CVE-2025-48044","tags":["related","web"]},{"url":"https://github.com/ash-project/ash/commit/79749c2685ea031ebb2de8cf60cc5edced6a8dd0","tags":["related","fix","web"]},{"url":"https://github.com/ash-project/ash/commit/8b83efa225f657bfc3656ad8ee8485f9b2de923d","tags":["patch","fix","web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2025-48044","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-pcxq-fjp3-r752"},{"url":"https://github.com","tags":["web"]},{"url":"https://repo.hex.pm","tags":["web"]},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2025/48xxx/CVE-2025-48044.json","tags":["advisory"]},{"url":"https://github.com/ash-project/ash","tags":["package"]},{"url":"https://hex.pm/packages/ash","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2025-48044","title":"Authorization bypass when bypass policy condition evaluates to true","description":"Incorrect Authorization vulnerability in ash-project ash allows Authentication Bypass.\n\nThis issue affects ash: from 3.6.3 before 3.7.1.","status":"published","published":"2025-10-17T13:52:53.644Z","modified":"2026-09-22T09:35:27.186Z","cvss":[{"version":"4.0","score":8.6,"vector":"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","level":"high","assessor":"cna"}],"cwes":["CWE-863"],"updated_at":"2026-11-02T14:32:41.41198Z"}],"euvd":[{"id":"EUVD-2025-34884","description":"Incorrect Authorization vulnerability in ash-project ash allows Authentication Bypass.\n\nThis issue affects ash: from 3.6.3 before 3.7.1.","status":"published","published":"2025-10-17T13:52:53Z","modified":"2026-09-22T09:35:27Z","cvss":[{"version":"4.0","score":8.6,"vector":"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","level":"high"}],"updated_at":"2026-11-02T17:28:03.79222Z"}],"ghsa":[{"id":"GHSA-pcxq-fjp3-r752","title":"Ash has authorization bypass when bypass policy condition evaluates to true","description":"### 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```","status":"published","published":"2025-10-17T18:03:06Z","modified":"2026-04-06T23:15:12Z","cvss":[{"version":"4.0","score":8.6,"vector":"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","level":"high"},{"version":"3.1","score":8.1,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N","level":"high"}],"cwes":["CWE-863"],"updated_at":"2026-11-02T14:39:50.076383Z"}],"nvd":[{"id":"CVE-2025-48044","description":"Incorrect Authorization vulnerability in ash-project ash allows Authentication Bypass.\n\nThis issue affects ash: from 3.6.3 before 3.7.1.","status":"published","published":"2025-10-17T14:15:46.403Z","modified":"2026-10-19T16:10:00.26Z","cvss":[{"version":"4.0","score":8.6,"vector":"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/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","level":"high","assessor":"secondary"}],"cwes":["CWE-863"],"updated_at":"2026-11-02T14:11:39.069866Z"}],"osv":[{"id":"CVE-2025-48044","title":"Authorization bypass when bypass policy condition evaluates to true","description":"Incorrect Authorization vulnerability in ash-project ash allows Authentication Bypass.\n\nThis issue affects ash: from 3.6.3 before 3.7.1.","status":"published","published":"2025-10-17T13:52:53.644Z","modified":"2026-10-28T02:30:24.540421786Z","cvss":[{"version":"4.0","score":8.6,"vector":"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","level":"high"}],"cwes":["CWE-863"],"updated_at":"2026-11-02T15:44:50.037003Z"},{"id":"EEF-CVE-2025-48044","title":"Authorization bypass when bypass policy condition evaluates to true","description":"## Summary\n\nIncorrect Authorization vulnerability in ash-project ash allows Authentication Bypass.\n\nThis issue affects ash: from 3.6.3 before 3.7.1.","status":"published","published":"2025-10-17T13:52:53.644Z","modified":"2026-09-22T09:45:03.76724012Z","cvss":[{"version":"4.0","score":8.6,"vector":"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","level":"high"}],"cwes":["CWE-863"],"updated_at":"2026-11-02T15:46:33.047032Z"},{"id":"GHSA-pcxq-fjp3-r752","title":"Ash has authorization bypass when bypass policy condition evaluates to true","description":"### 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```","status":"published","published":"2025-10-17T18:03:06Z","modified":"2026-07-08T07:14:05.301169272Z","cvss":[{"version":"3.1","score":8.1,"vector":"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N","level":"high"},{"version":"4.0","score":8.6,"vector":"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","level":"high"}],"cwes":["CWE-863"],"updated_at":"2026-11-02T15:46:52.891208Z"}]}}
