Skip to content

Commit 4ec8f44

Browse files
1 parent fcd637b commit 4ec8f44

File tree

1 file changed

+72
-0
lines changed

1 file changed

+72
-0
lines changed
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-pcxq-fjp3-r752",
4+
"modified": "2025-10-17T18:03:06Z",
5+
"published": "2025-10-17T18:03:06Z",
6+
"aliases": [
7+
"CVE-2025-48044"
8+
],
9+
"summary": "Ash has authorization bypass when bypass policy condition evaluates to true",
10+
"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\nBug introduced in PR #2365 (commit 79749c26).\n\nAffected line: [lib/ash/policy/policy.ex:69](https://github.com/ash-project/ash/blob/b2e4d625/lib/ash/policy/policy.ex#L69)\n```elixir\n{%{bypass?: true}, cond_expr, complete_expr}, {one_condition_matches, all_policies_match} ->\n {\n b(cond_expr or one_condition_matches), # <- 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} ->\n {\n b(complete_expr or one_condition_matches), # <- 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} ->\n {\n b(complete_expr or one_condition_matches), # <- 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```",
11+
"severity": [
12+
{
13+
"type": "CVSS_V3",
14+
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N"
15+
},
16+
{
17+
"type": "CVSS_V4",
18+
"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"
19+
}
20+
],
21+
"affected": [
22+
{
23+
"package": {
24+
"ecosystem": "Hex",
25+
"name": "ash"
26+
},
27+
"ranges": [
28+
{
29+
"type": "ECOSYSTEM",
30+
"events": [
31+
{
32+
"introduced": "3.6.3"
33+
},
34+
{
35+
"fixed": "3.7.1"
36+
}
37+
]
38+
}
39+
],
40+
"database_specific": {
41+
"last_known_affected_version_range": "<= 3.7.0"
42+
}
43+
}
44+
],
45+
"references": [
46+
{
47+
"type": "WEB",
48+
"url": "https://github.com/ash-project/ash/security/advisories/GHSA-pcxq-fjp3-r752"
49+
},
50+
{
51+
"type": "ADVISORY",
52+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-48044"
53+
},
54+
{
55+
"type": "WEB",
56+
"url": "https://github.com/ash-project/ash/commit/8b83efa225f657bfc3656ad8ee8485f9b2de923d"
57+
},
58+
{
59+
"type": "PACKAGE",
60+
"url": "https://github.com/ash-project/ash"
61+
}
62+
],
63+
"database_specific": {
64+
"cwe_ids": [
65+
"CWE-863"
66+
],
67+
"severity": "HIGH",
68+
"github_reviewed": true,
69+
"github_reviewed_at": "2025-10-17T18:03:06Z",
70+
"nvd_published_at": "2025-10-17T14:15:46Z"
71+
}
72+
}

0 commit comments

Comments
 (0)