CVE-2026-80223 Overview
CVE-2026-80223 is an Incorrect Authorization vulnerability [CWE-863] in the ash-project/ash_graphql library for Elixir. The flaw allows an authenticated subscriber in one tenant to receive another tenant's records through GraphQL subscriptions. The subscription resolver in AshGraphql.Graphql.Resolver authorizes each notification payload in memory without applying the tenant condition. The issue affects ash_graphql from version 1.4.0 up to but not including 1.11.0.
Critical Impact
Cross-tenant data leakage over GraphQL subscriptions. Records belonging to tenant B can be delivered to a tenant A subscriber whenever the in-memory read policy filter evaluates to true.
Affected Products
- ash_graphql 1.4.0 through versions prior to 1.11.0
- Elixir applications using AshGraphql subscription resolvers with multitenancy
- GraphQL APIs relying on Ash multitenancy for tenant isolation on subscription channels
Discovery Timeline
- 2026-08-30 - CVE-2026-80223 published to NVD
- 2026-09-03 - Last updated in NVD database
Technical Details for CVE-2026-80223
Vulnerability Analysis
The defect resides in the subscription resolver's authorization fast path. The resolver calls Ash.can/3 with run_queries?: false for each notification payload. This evaluates the read policy filter against the in-memory record using Ash.Expr.eval/2 and never issues a database query. Because Ash enforces multitenancy at query-build time and at the data-layer prefix, the in-memory evaluation carries no tenant condition. A notification produced for tenant B is emitted to a tenant A subscriber whenever the policy filter evaluates to true against the record.
Root Cause
Two code paths compound the issue. The single-notification clause contains no tenant guard whatsoever. The batched clause checks tenancy only on the head of the notification list, so remaining entries are authorized purely against in-memory state. The tenant-scoped read that would enforce isolation is only reached when the filter evaluation fails, which is the opposite of a fail-closed design.
Attack Vector
An authenticated subscriber in one tenant establishes a GraphQL subscription. When events are published for a different tenant and routed through the batched or single-notification path, the missing tenant guard delivers records to the wrong tenant. Exploitation requires low privileges and no user interaction over the network, and it affects confidentiality of other tenants' data.
// Patch excerpt: enforce tenant on every subscription notification, not just the batch head
subscription_events =
notifications
+ # Only the list head was tenant-checked (see the guard clause above);
+ # drop any other-tenant notifications here so the batch can't leak them.
+ |> reject_other_tenant_notifications(context)
|> Enum.group_by(& &1.action_type)
|> Enum.map(fn {type, notifications} ->
subscription_field = subcription_field_from_action_type(type)
Source: GitHub Commit 6e30b8b
Detection Methods for CVE-2026-80223
Indicators of Compromise
- GraphQL subscription responses containing record identifiers, primary keys, or tenant attributes that do not match the subscriber's tenant context.
- Application logs showing subscription payload deliveries where the notification's tenant differs from the connected session's tenant.
- Elevated subscription event volume on resources shared across tenants without a corresponding legitimate tenant scope.
Detection Strategies
- Audit installed ash_graphql versions across services and flag any release in the range 1.4.0 through versions earlier than 1.11.0.
- Instrument the subscription resolver to log the notification tenant and the subscriber tenant, then alert when they differ.
- Add integration tests that publish tenant-B notifications on channels held by tenant-A subscribers and assert zero deliveries.
Monitoring Recommendations
- Ingest GraphQL subscription telemetry and Elixir application logs into a centralized log platform and correlate on tenant identifiers.
- Track WebSocket subscription sessions per tenant and alert on records emitted with mismatched tenant attributes.
- Monitor dependency manifests (mix.exs, mix.lock) in CI for vulnerable ash_graphql versions.
How to Mitigate CVE-2026-80223
Immediate Actions Required
- Upgrade ash_graphql to version 1.11.0 or later in all affected Elixir services.
- Review GraphQL subscription resolvers that rely on Ash multitenancy and confirm the tenant guard is enforced for every notification.
- Rotate credentials or invalidate active subscription sessions if cross-tenant leakage is suspected from historical logs.
Patch Information
The fix is in commit 6e30b8b5a04bdeaed5d7514caa6b2d056d8d993e, which introduces reject_other_tenant_notifications/2 to filter every notification in a batch against the subscriber's tenant context. Reference the GitHub Security Advisory GHSA-rcqc-59g2-gjg2, the CNA CVE-2026-80223 Details, and the OSV entry EEF-CVE-2026-80223 for the full advisory.
Workarounds
- Disable GraphQL subscriptions on resources that use Ash multitenancy until the upgrade to 1.11.0 is deployed.
- Add an application-level check in the subscription resolver that compares the notification's tenant to the session's tenant and drops mismatches.
- Restrict subscription access at the gateway or authentication layer so subscribers cannot subscribe to resources outside their tenant scope.
# Update ash_graphql in mix.exs and lock file
# mix.exs
# {:ash_graphql, "~> 1.11.0"}
mix deps.update ash_graphql
mix deps.get
mix compile --force
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.