Skip to content
Heist/ feed
Back to feed
MediumFix available

AshPostgres returns another tenant's record for a skipped upsert when return_skipped_upsert? is set

Type: advisorySources: OSV

## Summary 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. ## Impact A user of one tenant whose upsert is skipped receives another tenant's record with the same identity values. ## Configurations Reachable when a resource uses attribute multitenancy, an action performs upserts with `return_skipped_upsert?: true`, and a caller can supply identity values that another tenant also uses.

Products
ash_postgres
Affected versions
2.10.0, 2.11.0, 2.12.0, 2.13.0, 2.13.1, 2.14.0, 2.14.1, 2.14.2, 2.14.3, 2.14.4, 2.14.5, 2.15.0, 2.15.1, 2.6.22, 2.6.23, 2.6.24, 2.6.25, 2.6.26, 2.6.27, 2.6.28, 2.6.29, 2.6.30, 2.6.31, 2.6.32, 2.7.0, 2.8.0, 2.9.0, 2.9.1
Fixed versions
2.15.2
CVEs
CVE-2026-115635
Confirmed fixed CVEs
Not specified
Updated in this feed
1 Nov 2026, 10:26 UTC · Revision 1

Source evidence

AshPostgres returns another tenant's record for a skipped upsert when return_skipped_upsert? is set

core-osv · Original source

Published 25 Oct 2026, 19:48 UTC

## Summary 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. ## Impact A user of one tenant whose upsert is skipped receives another tenant's record with the same identity values. ## Configurations Reachable when a resource uses attribute multitenancy, an action performs upserts with `return_skipped_upsert?: true`, and a caller can supply identity values that another tenant also uses.

osv:EEF-CVE-2026-115635

ash_postgres

Fixed versions: 2.15.2

Complete source record
{
  "id": "731b9342bd51f586303b8d56fa58dbd5d8b72324645f7f7dd539cda9f2e6b258",
  "url": "https://osv.dev/vulnerability/EEF-CVE-2026-115635",
  "method": "structured",
  "payload": {
    "kind": "advisory",
    "title": "AshPostgres returns another tenant's record for a skipped upsert when return_skipped_upsert? is set",
    "summary": "## Summary 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. ## Impact A user of one tenant whose upsert is skipped receives another tenant's record with the same identity values. ## Configurations Reachable when a resource uses attribute multitenancy, an action performs upserts with `return_skipped_upsert?: true`, and a caller can supply identity values that another tenant also uses.",
    "evidence": "osv:EEF-CVE-2026-115635",
    "products": [
      {
        "name": {
          "value": "ash_postgres",
          "evidence": "/affected/0/package/name"
        },
        "prerequisites": [],
        "fixed_versions": [
          {
            "value": "2.15.2",
            "evidence": "/affected/0/ranges"
          }
        ],
        "affected_versions": [
          {
            "value": "2.10.0",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.11.0",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.12.0",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.13.0",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.13.1",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.14.0",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.14.1",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.14.2",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.14.3",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.14.4",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.14.5",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.15.0",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.15.1",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.6.22",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.6.23",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.6.24",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.6.25",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.6.26",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.6.27",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.6.28",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.6.29",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.6.30",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.6.31",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.6.32",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.7.0",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.8.0",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.9.0",
            "evidence": "/affected/0/versions"
          },
          {
            "value": "2.9.1",
            "evidence": "/affected/0/versions"
          }
        ]
      }
    ],
    "severity": "medium",
    "structured": {
      "id": "EEF-CVE-2026-115635",
      "aliases": [
        "CVE-2026-115635",
        "EEF-CVE-2026-115635",
        "GHSA-36hg-wwp2-fg8w"
      ],
      "metrics": [
        {
          "type": "CVSS_V4",
          "score": "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"
        }
      ],
      "affected": [
        {
          "ranges": [
            {
              "type": "SEMVER",
              "events": [
                {
                  "introduced": "2.6.22"
                },
                {
                  "fixed": "2.15.2"
                }
              ]
            }
          ],
          "package": {
            "name": "ash_postgres",
            "purl": "pkg:hex/ash_postgres",
            "ecosystem": "Hex"
          },
          "versions": [
            "2.10.0",
            "2.11.0",
            "2.12.0",
            "2.13.0",
            "2.13.1",
            "2.14.0",
            "2.14.1",
            "2.14.2",
            "2.14.3",
            "2.14.4",
            "2.14.5",
            "2.15.0",
            "2.15.1",
            "2.6.22",
            "2.6.23",
            "2.6.24",
            "2.6.25",
            "2.6.26",
            "2.6.27",
            "2.6.28",
            "2.6.29",
            "2.6.30",
            "2.6.31",
            "2.6.32",
            "2.7.0",
            "2.8.0",
            "2.9.0",
            "2.9.1"
          ],
          "database_specific": {
            "source": "https://cna.erlef.org/osv/EEF-CVE-2026-115635.json"
          }
        },
        {
          "ranges": [
            {
              "repo": "https://github.com/ash-project/ash_postgres",
              "type": "GIT",
              "events": [
                {
                  "introduced": "af0903f1380468bbe1b61fe65acb33772b5e24a5"
                },
                {
                  "fixed": "8aa81220c401cae412d21078d11b3519ea25d3a9"
                }
              ]
            }
          ],
          "versions": [
            "v2.15.1",
            "v2.15.0",
            "v2.14.5",
            "v2.14.4",
            "v2.14.3",
            "v2.14.2",
            "v2.14.1",
            "v2.14.0",
            "v2.13.1",
            "v2.13.0",
            "v2.12.0",
            "v2.11.0",
            "v2.10.0",
            "v2.9.1",
            "v2.9.0",
            "v2.8.0",
            "v2.7.0",
            "v2.6.32",
            "v2.6.31",
            "v2.6.30",
            "v2.6.29",
            "v2.6.28",
            "v2.6.27",
            "v2.6.26",
            "v2.6.25",
            "v2.6.24",
            "v2.6.23",
            "v2.6.22"
          ],
          "database_specific": {
            "source": "https://cna.erlef.org/osv/EEF-CVE-2026-115635.json"
          }
        }
      ],
      "modified": "2026-10-25T20:11:06.333036314Z",
      "provider": "osv",
      "references": [
        "https://github.com/ash-project/ash/security/advisories/GHSA-36hg-wwp2-fg8w",
        "https://cna.erlef.org/cves/CVE-2026-115635.html",
        "https://github.com/ash-project/ash_postgres/commit/af0903f1380468bbe1b61fe65acb33772b5e24a5",
        "https://github.com/ash-project/ash_postgres/commit/8aa81220c401cae412d21078d11b3519ea25d3a9",
        "https://hex.pm/packages/ash_postgres"
      ],
      "provider_metadata": {
        "cpe_ids": [
          "cpe:2.3:a:ash-project:ash_postgres:*:*:*:*:*:*:*:*"
        ],
        "cwe_ids": [
          "CWE-863"
        ],
        "capec_ids": [
          "CAPEC-1"
        ]
      }
    },
    "related_cves": [
      {
        "value": "CVE-2026-115635",
        "evidence": "/aliases"
      }
    ],
    "security_relevant": true,
    "severity_evidence": "/severity/0/score"
  },
  "source_id": "core-osv",
  "document_id": 446220,
  "published_at": "2026-10-25T19:48:43.829+00:00"
}