{"id":"CVE-2025-48043","aliases":["EEF-CVE-2025-48043","GHSA-7r7f-9xpj-jmr7"],"url":"https://o3.security/vulnerability/CVE-2025-48043","summary":"Bypass and runtime policies that can never pass may be incorrectly applied in filter authorization","details":"### Summary\n\nWhen using **filter** authorization, two edge cases could cause the policy compiler/authorizer to generate a permissive filter:\n\n1. **Bypass policies whose condition can never pass at runtime** were compiled as\n   `OR(AND(condition, compiled_policies), NOT(condition))`.\n   If the condition could never be true at runtime, the `NOT(condition)` branch evaluated truthy and the overall expression became permissive.\n\n2. **Runtime policy scenarios that reduce to “no checks are applicable”** (an empty SAT scenario) were treated as an empty clause and dropped instead of being treated as **`false`**, which could again produce an overly broad (permissive) filter.\n\nThese bugs could allow reads to return records that should have been excluded by policy.\n\n### Impact\n\nProjects that rely on **filter-based authorization** and define:\n\n* `bypass ... do ... end` blocks whose condition(s) are only resolvable at runtime and can never pass in a given request context, **or**\n* runtime checks that simplify to an **empty** scenario for a clause\n\nmay unintentionally generate a permissive query filter, potentially returning unauthorized data.\n\n*Actions primarily affected:* reads guarded by filter policies. Non-filter (e.g., hard forbid) policies are not impacted.\n\n### Technical details\n\nThis patch corrects two behaviors:\n\n* **`Ash.Policy.Policy.compile_policy_expression/1`** now treats **bypass** blocks as\n  `AND(condition_expression, compiled_policies)`\n  instead of `OR(AND(...), NOT(condition_expression))`. This removes the permissive `NOT(condition)` escape hatch when a bypass condition never passes.\n\n* **`Ash.Policy.Authorizer`** now treats **empty SAT scenarios** (`scenario == %{}`) as **`false`**, ensuring impossible scenarios do not collapse into a no-op and inadvertently widen the filter. The reducer also normalizes `nil` → `false` consistently when building `auto_filter` fragments.\n\nRelevant changes are in:\n\n* `lib/ash/policy/policy.ex` (bypass compilation)\n* `lib/ash/policy/authorizer/authorizer.ex` (scenario handling / auto_filter normalization)\n* Tests added: `test/policy/filter_condition_test.exs` (`RuntimeFalsyCheck`, `RuntimeBypassResource`) validate the corrected behavior.\n\n### Workarounds\n\n* Avoid `bypass` policies whose conditions are only decidable at runtime and may be perpetually false in some contexts; prefer explicit `authorize_if`/`forbid_if` blocks without `bypass` for those cases.\n* Add an explicit **final `forbid_if always()`** guard for sensitive reads as a belt-and-suspenders fallback until user can upgrade.\n* Where feasible, replace runtime-unknown checks with strict/compile-time checks or restructure to avoid empty SAT scenarios.\n\n### How to tell if user is affected\n\nUser is likely affected if ALL of the following are true:\n\n*  Uses **filter authorization**; and\n* Defines `bypass` block with `access_type :runtime` without any policies after it; or\n* Defines `bypass` blocks whose conditions are evaluated at runtime (e.g., checks with `strict_check/3` returning `:unknown` and a runtime `check/4` that may never succeed in some contexts) without any policies after it\n\nA quick sanity test is to issue a read expected to return **no** rows under such a bypass or runtime-falsy condition and verify it indeed returns `[]`. The included test `bypass works with filter policies` demonstrates the corrected, non-permissive behavior.","published":"2025-10-10T15:57:29.225Z","modified":"2026-09-24T03:45:10.555128170Z","cvss":null,"epss":null,"cisaKev":null,"exploitsKnown":0,"affectedPackages":[{"ecosystem":"Hex","name":"ash","fixedVersion":"3.6.2"}],"fix":{"url":"https://github.com/ash-project/ash/commit/4c41344126b0aba09ec3085517000f8aefec299e","label":"ash-project/ash@4c41344"},"references":[{"type":"WEB","url":"https://cna.erlef.org/cves/CVE-2025-48043.html"},{"type":"WEB","url":"https://github.com"},{"type":"WEB","url":"https://osv.dev/vulnerability/EEF-CVE-2025-48043"},{"type":"WEB","url":"https://repo.hex.pm"},{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2025/48xxx/CVE-2025-48043.json"},{"type":"ADVISORY","url":"https://github.com/ash-project/ash/security/advisories/GHSA-7r7f-9xpj-jmr7"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2025-48043"},{"type":"FIX","url":"https://github.com/ash-project/ash/commit/4c41344126b0aba09ec3085517000f8aefec299e"},{"type":"FIX","url":"https://github.com/ash-project/ash/commit/66d81300065b970da0d2f4528354835d2418c7ae"},{"type":"PACKAGE","url":"https://github.com/ash-project/ash"},{"type":"WEB","url":"https://github.com/ash-project/ash/releases/tag/v3.6.2"}],"provenance":{"sources":["OSV.dev","FIRST.org (EPSS)"],"lastVerified":"2026-09-24T03:45:10.555128170Z"}}