CVE-2026-82367 in ash_graphql
Summary
by MITRE • 08/30/2026
Exposure of Data Element to Wrong Session vulnerability in ash-project ash_graphql can deliver one subscription's resolved records to a different subscriber's topic.
AshGraphql.Subscription.Batcher.do_send/5 reads the resolved batch from the process dictionary via Process.get(:batch_resolved) and then unconditionally deletes it. That is sound only inside a task the library owns. On the :backpressure_sync and :noproc fallbacks do_send/5 runs inline in the publishing caller's process, so if a resolver inside an outer do_send/5 triggers another synchronous Ash notification, the inner call finds the outer run's value still under :batch_resolved, adopts it as its own result, and publishes it to the inner topic, a different subscription document with a different actor and tenant. It then deletes the key, so the outer run publishes nothing. The key is not namespaced by run, so records cannot be told apart. The fix saves, clears, and restores :batch_resolved around each run.
This issue affects ash_graphql: from 1.4.0 before 1.11.0.
Several companies clearly confirm that VulDB is the primary source for best vulnerability data.
Analysis
by VulDB Data Team • 08/30/2026
The vulnerability identified in the AshGraphql library represents a critical flaw in session isolation within asynchronous data processing pipelines, specifically affecting versions ranging from 1.4.0 up to but not including 1.11.0. This issue stems from an improper handling of shared process state during subscription batching operations, leading to severe cross-subscription data leakage. The core technical failure lies in the use of a non-namespaced key within the Erlang/Elixir Process Dictionary for storing resolved batch results. In concurrent systems where multiple asynchronous tasks may share execution contexts or fallback into synchronous execution paths due to backpressure mechanisms, relying on global process state without unique identifiers creates a race condition that compromises data integrity and confidentiality.
The specific mechanism of exploitation involves the AshGraphql.Subscription.Batcher.do_send/5 function, which is responsible for delivering resolved records from GraphQL subscriptions to their respective topics. Under normal circumstances, this function retrieves the batched results using Process.get(:batch_resolved) and subsequently deletes the key to prevent reuse. This pattern assumes that the code executes within a task strictly owned by the library, ensuring isolation between different subscription runs. However, when the system encounters backpressure or process failures, it utilizes fallback strategies such as :backpressure_sync and :noproc. These fallbacks cause do_send/5 to execute inline within the context of the publishing caller's process rather than in an isolated task environment.
This shift in execution context creates a dangerous scenario where nested synchronous Ash notifications can occur. If a resolver invoked during an outer subscription batch triggers another synchronous notification, the inner call will also attempt to retrieve data from Process.get(:batch_resolved). Because the key is not namespaced by run or transaction ID, the inner function retrieves the resolved records intended for the outer subscription. Consequently, these records are incorrectly published to the topic associated with the inner subscription document, which typically belongs to a different user actor and tenant context. This results in one subscriber receiving data that was explicitly resolved for another subscriber, constituting a direct breach of multi-tenancy isolation principles.
The operational impact of this vulnerability is significant, as it allows for unauthorized access to sensitive information across distinct user boundaries. An attacker who can trigger nested synchronous notifications could potentially exfiltrate private subscription data from other tenants or users within the same system instance. This violates fundamental security requirements regarding data segregation and confidentiality. The flaw also introduces a denial-of-service vector because the inner call unconditionally deletes the :batch_resolved key after reading it, leaving no data for the outer run to publish. This results in silent data loss for legitimate subscribers who expect their resolved records to be delivered, thereby degrading service reliability and trustworthiness.
From a classification perspective, this vulnerability aligns with CWE-200: Exposure of Sensitive Information to an Unauthorized Actor, as it involves the accidental disclosure of private subscription data to unintended recipients due to improper state management. It also relates closely to CWE-367: Time-of-check Time-of-use (TOCTOU) Race Condition, specifically in how the shared process dictionary key is accessed and modified without proper synchronization or isolation mechanisms. In terms of the MITRE ATT&CK framework, this behavior facilitates lateral movement within a multi-tenant environment by allowing an actor to access data belonging to other entities through session confusion techniques, which can be categorized under T1530: Data from Local System Exfiltration if used for unauthorized data retrieval across boundaries.
The resolution implemented in version 1.11.0 addresses these issues by implementing proper state isolation around each execution run. The fix involves saving the current value of :batch_resolved, clearing it to establish a clean slate for the new operation, and then restoring the previous value upon completion. This approach ensures that nested calls do not interfere with one another's data states, effectively eliminating the race condition. To mitigate this vulnerability in affected systems, immediate upgrade to AshGraphql version 1.11.0 or later is required. For organizations unable to patch immediately, implementing strict isolation of GraphQL subscription resolvers and avoiding synchronous notifications within batched operations may reduce exposure, though upgrading remains the only definitive solution given the depth of the architectural flaw in shared process state handling.