Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
AccessAuthenticate as a tenant user
-
DeliverySubmit upsert with return_skipped_upsert? and colliding identity values
-
ExploitUpsert skipped because upsert_condition fails
-
ExecutionRead-back query omits attribute tenant filter
-
ImpactReceive another tenant's matching record
Vulnerability Assessment
| Weakness |
CWE
OWASP Top 10:2025
A01:2025 - Broken Access Control
ASVS 5.0
V8 - Authorization Authorization logic validation
MITRE ATT&CK
1 technique across 1 tactic: Privilege Escalation The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up. |
| Exploitation Conditions | Exploitation requires a specific, non-default combination stated in the advisory: the resource must use attribute multitenancy (strategy :attribute); an action must perform upserts with return_skipped_upsert?: true; the upsert must actually be skipped (e.g. its upsert_condition does not hold); and the authenticated caller must be able to supply identity values that another tenant also uses. Limiting factors that reduce real-world risk: it needs authenticated tenant-level access (PR:L), it only triggers on this opt-in return_skipped_upsert? code path rather than ordinary creates, exposure is confined to rows whose identity values collide across tenants, and impact is read-only disclosure (no write or availability effect). |
| Impact | This is a genuine but moderate-priority issue, consistent with its 6.0 (Medium) score. The supplied CVSS 4.0 vector (AV:N/AC:L/AT:P/PR:L/UI:N/VC:H/VI:N/VA:N) indicates a network-reachable, confidentiality-only flaw that requires an authenticated caller (PR:L) and carries an explicit attack requirement (AT:P) - the precondition that another tenant holds a record with the same identity values and that the upsert is actually skipped. These conditions are not fully attacker-controlled, which is what keeps this below critical. The vuln.today decision label is 'this_month' (not act_now/emergency), aligning with the moderate severity. No EPSS probability was provided in the input, there is no CISA KEV listing (not actively exploited), and no public exploit was identified at time of analysis - only the vendor patch commit and a regression test accompany the advisory. Signals are internally consistent: a real tenant-isolation/authorization defect worth remediating in normal patch cycles rather than an emergency, with real-world exposure further limited by the non-default opt-in configuration required to reach it. |
| Exploit ScenarioDerived | An authenticated user acting as one tenant invokes an upsert-based create (via Ash.bulk_create/4 or a single create) with return_skipped_upsert?: true, supplying identity values that collide with a record owned by a different tenant. Because the upsert_condition does not hold, the upsert is skipped and AshPostgres.DataLayer reads the existing row back by identity without applying attribute multitenancy, returning the other tenant's record fields to the caller. No public exploit was identified at time of analysis, though a regression test demonstrating the skipped-upsert path ships with the fix. |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – Oct 25, 2026
AshPostgres versions 2.6.22 through 2.15.1 can disclose another tenant's row to an authenticated caller when an upsert is skipped and the action was invoked with return_skipped_upsert?: true. The vulnerable read-back in do_bulk_create/3 and upsert/4 re-fetched the existing row by upsert identity without applying the resource's attribute multitenancy (strategy :attribute), so an identity collision across tenants could return the wrong tenant's field values; the exposure is read-only disclosure of the matched row, with no write or availability impact. Exploitation requires the non-default combination documented in the advisory - attribute multitenancy, an upsert action with return_skipped_upsert?: true, an upsert that is actually skipped, and caller-supplied identity values that another tenant also uses - and no public exploit code or CISA KEV entry was identified at time of analysis; vendor-released patch: 2.15.2.
RemediationAI
Upgrade ash_postgres to 2.15.2 or later, which contains the fix in commit 8aa81220c401cae412d21078d11b3519ea25d3a9 (the companion commit af0903f1380468bbe1b61fe65acb33772b5e24a5 is also referenced); the same commit raises the ash dependency requirement to ~> 3.5 and >= 3.6.2 and igniter to >= 0.6.29, so refresh the lockfile and rebuild after upgrading. Full details are in the vendor advisory at https://github.com/ash-project/ash/security/advisories/GHSA-36hg-wwp2-fg8w and the CNA record at https://cna.erlef.org/cves/CVE-2026-115635.html. If upgrading cannot be done immediately, the advisory's stated prerequisites define the exposure surface: resources using attribute multitenancy whose actions invoke upserts with return_skipped_upsert?: true. Staying off that opt-in code path (not requesting skipped-upsert rows on attribute-multitenant resources) avoids the vulnerable read-back, at the cost of losing that return value for callers who rely on it, and ensuring identity values cannot collide across tenants reduces but does not eliminate the mismatch; the vendor's complete fix is the 2.15.2 upgrade. Priority per the supplied decision signal is this_month rather than emergency, and there is no KEV entry or confirmed working exploit code to accelerate the timeline.
Affected VersionsENISA
Affected Packages
Source: OSV (Open Source Vulnerabilities)
Affects your stack
Affects 1 package in euvd
Checking this CVE against your own stacks and servers is part of the Basic plan and up.
Technical ContextAI · show details
AshPostgres is the PostgreSQL data layer for the Ash framework in Elixir, translating Ash resource actions into Ecto queries. Ash supports multitenancy strategies including :attribute, where the tenant is carried as a column/attribute on the resource rather than by a separate schema or database. When Ash.bulk_create/4 or a single create is run as an upsert with return_skipped_upsert?: true, the data layer must return a row even when the insert is skipped (for example because upsert_condition does not hold), so it reads the pre-existing row back by the upsert identity keys - by default the primary key, or identity.keys when an identity is supplied. That lookup in do_bulk_create/3 and upsert/4 omitted the resource's attribute multitenancy filter, so the identity match was effectively tenant-blind. The result is a CWE-863 incorrect authorization flaw: the caller is authorized for its own tenant scope but receives a row resolved outside that scope. The upstream fix (commit af0903f1) performs the skipped-upsert read-back through an Ash query built from the changesets' identity attributes, additionally constrained by identity.where when present, and scoped with Ash.Query.set_tenant(changeset.tenant); it also re-maps results back to changesets by identity keys, adds a :bulk_upsert_return_skipped data layer capability, and bumps the ash dependency floor to >= 3.6.2 (igniter to >= 0.6.29) in mix.exs. The trigger requires the specific opt-in code path and configuration described in the advisory; behavior of other create paths is not described as affected in the available sources.
Know when Ash Postgres gets its next vulnerability
- Watch products and get an email when something new is published
- Check this CVE against your own stack and servers
- Exploit and PoC references, threat intelligence from 22 sources
No credit card · 7-day full trial
Severity by source
CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N
Authenticated tenant caller (PR:L) over a network API (AV:N); the required cross-tenant identity collision and skipped upsert are attacker-uncontrolled preconditions (AC:H); read-only disclosure (C:H, I/A:N).
Primary rating from Vendor (EEF).
CVSS VectorVendor: EEF
DescriptionCVE.org
Incorrect Authorization vulnerability in ash-project ash_postgres allows a user to read another tenant's record through a skipped upsert.
When Ash.bulk_create/4 or a single create runs as an upsert with return_skipped_upsert?: true and the upsert is skipped (for example because its upsert_condition does not hold), AshPostgres.DataLayer reads the existing row back by the upsert identity in do_bulk_create/3 and upsert/4. That lookup did not apply the resource's attribute multitenancy, so on a resource using strategy :attribute it could match and return the row of another tenant with the same identity values, exposing its fields to the caller.
This issue affects ash_postgres: from 2.6.22 before 2.15.2.
Threat Intelligence Overview
How this decision was reached
The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.
What every action level means
SSVC AssessmentENISA
Priority Score
Attack Technique
Authentication bypass attacks exploit flaws in the verification mechanisms that control access to systems and applications.
More in Ash Postgres
View allSilent schema cross-contamination in ash_postgres multi-tenancy allows a low-privileged user who can trigger a tenant re
Cross-tenant record disclosure in AshPostgres 0.38.0 through 2.15.1 lets an authenticated tenant user load destination r
EUVD-2026-109568
NVD
CVE.org
EPSS
Vulnrichment
GitHub
VulDB
Exploit-DB