CVE-2026-17349 (GCVE-0-2026-17349)
Vulnerability from cvelistv5
Published
2026-07-31 15:59
Modified
2026-08-01 03:56
CWE
  • CWE-639 - Authorization Bypass Through User-Controlled Key
  • CWE-522 - Insufficiently Protected Credentials
Summary
/misc/workspace/adhoc_connect_server, part of the Workspaces feature introduced in pgAdmin 4 9.0, when passed the id of an existing server, clones that server via Server.clone(), which copies every column from the source row, including user_id, shared, shared_username, and the stored credential fields password, save_password, and tunnel_password. When a non-owner triggered an adhoc connect against another user's (in practice, typically an administrator's) shared server, the clone inherited that user's ownership, shared flag, and stored database credentials verbatim. pgAdmin persisted this cross-tenant, credential-bearing server row before the connection was even attempted, so it survived even when the connection subsequently failed. The non-owner could then open the newly-owned clone and pgAdmin would connect using the source user's stored database password on the non-owner's behalf, granting the non-owner use of database credentials -- and whatever database privileges they confer -- that were never their own. Fix forces the cloned adhoc record's ownership fields (user_id, shared, shared_username) and stored credential fields (password, save_password, tunnel_password) to belong to the calling user and be cleared/private before committing, regardless of the source server's ownership, sharing state, or stored credentials. A regression test asserts that an adhoc connect triggered by a non-owner against another user's shared server persists a row owned by the caller, not shared, and without the source's stored credentials. This issue affects pgAdmin 4: from 9.0 before 9.17.
Impacted products
Vendor Product Version
pgadmin.org pgAdmin 4 Version: 9.0   < 9.17
Create a notification for this product.
Show details on NVD website


{
  "containers": {
    "adp": [
      {
        "metrics": [
          {
            "other": {
              "content": {
                "id": "CVE-2026-17349",
                "options": [
                  {
                    "Exploitation": "none"
                  },
                  {
                    "Automatable": "no"
                  },
                  {
                    "Technical Impact": "total"
                  }
                ],
                "role": "CISA Coordinator",
                "timestamp": "2026-07-31T00:00:00+00:00",
                "version": "2.0.3"
              },
              "type": "ssvc"
            }
          }
        ],
        "providerMetadata": {
          "dateUpdated": "2026-08-01T03:56:26.176Z",
          "orgId": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
          "shortName": "CISA-ADP"
        },
        "title": "CISA ADP Vulnrichment"
      }
    ],
    "cna": {
      "affected": [
        {
          "defaultStatus": "unaffected",
          "modules": [
            "Workspaces"
          ],
          "product": "pgAdmin 4",
          "programFiles": [
            "https://github.com/pgadmin-org/pgadmin4/blob/master/web/pgadmin/misc/workspaces/__init__.py"
          ],
          "repo": "https://github.com/pgadmin-org/pgadmin4",
          "vendor": "pgadmin.org",
          "versions": [
            {
              "lessThan": "9.17",
              "status": "affected",
              "version": "9.0",
              "versionType": "custom"
            }
          ]
        }
      ],
      "credits": [
        {
          "lang": "en",
          "type": "finder",
          "value": "Ashesh Vashi \u003cashesh.vashi@enterprisedb.com\u003e"
        },
        {
          "lang": "en",
          "type": "remediation developer",
          "value": "Ashesh Vashi \u003cashesh.vashi@enterprisedb.com\u003e"
        },
        {
          "lang": "en",
          "type": "remediation reviewer",
          "value": "Kundan Sable \u003ckundan.sable@enterprisedb.com\u003e"
        }
      ],
      "descriptions": [
        {
          "lang": "en",
          "value": "/misc/workspace/adhoc_connect_server, part of the Workspaces feature introduced in pgAdmin 4 9.0, when passed the id of an existing server, clones that server via Server.clone(), which copies every column from the source row, including user_id, shared, shared_username, and the stored credential fields password, save_password, and tunnel_password. When a non-owner triggered an adhoc connect against another user\u0027s (in practice, typically an administrator\u0027s) shared server, the clone inherited that user\u0027s ownership, shared flag, and stored database credentials verbatim. pgAdmin persisted this cross-tenant, credential-bearing server row before the connection was even attempted, so it survived even when the connection subsequently failed. The non-owner could then open the newly-owned clone and pgAdmin would connect using the source user\u0027s stored database password on the non-owner\u0027s behalf, granting the non-owner use of database credentials -- and whatever database privileges they confer -- that were never their own.\n\nFix forces the cloned adhoc record\u0027s ownership fields (user_id, shared, shared_username) and stored credential fields (password, save_password, tunnel_password) to belong to the calling user and be cleared/private before committing, regardless of the source server\u0027s ownership, sharing state, or stored credentials. A regression test asserts that an adhoc connect triggered by a non-owner against another user\u0027s shared server persists a row owned by the caller, not shared, and without the source\u0027s stored credentials.\n\nThis issue affects pgAdmin 4: from 9.0 before 9.17."
        }
      ],
      "metrics": [
        {
          "cvssV3_1": {
            "attackComplexity": "LOW",
            "attackVector": "NETWORK",
            "availabilityImpact": "NONE",
            "baseScore": 9.6,
            "baseSeverity": "CRITICAL",
            "confidentialityImpact": "HIGH",
            "integrityImpact": "HIGH",
            "privilegesRequired": "LOW",
            "scope": "CHANGED",
            "userInteraction": "NONE",
            "vectorString": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N",
            "version": "3.1"
          },
          "format": "CVSS",
          "scenarios": [
            {
              "lang": "en",
              "value": "Threat model: an authenticated, low-privilege pgAdmin user who knows or can enumerate the server id of another user\u0027s (e.g. an administrator\u0027s) shared server row triggers an adhoc connect against it. No special privilege beyond ordinary authenticated access is needed, and no interaction from the victim is required. Scope is Changed: the attacker\u0027s own pgAdmin authorization does not itself grant use of the source user\u0027s stored database credentials, so gaining and using those credentials crosses into another user\u0027s security authority -- specifically the database privileges the source user\u0027s stored credentials confer, which may substantially exceed the attacker\u0027s own. Confidentiality and Integrity are High because the attacker obtains a working, reusable database credential and can use it to read/write whatever the source user\u0027s database role permits. Availability is None: the leak itself does not directly cause denial of service."
            }
          ]
        },
        {
          "cvssV4_0": {
            "baseScore": 9.3,
            "baseSeverity": "CRITICAL",
            "vectorString": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:N/SC:H/SI:H/SA:N",
            "version": "4.0"
          },
          "format": "CVSS",
          "scenarios": [
            {
              "lang": "en",
              "value": "Same reasoning as the CVSS 3.1 entry: an authenticated low-privilege user obtains another user\u0027s stored database credential via server cloning, without any interaction from the victim. VC:H/VI:H for pgAdmin\u0027s own scope (the leaked credential itself); SC:H/SI:H because the credential is then usable against the underlying database server, a subsequent system whose privileges may substantially exceed the attacker\u0027s own. VA:N/SA:N since the leak alone does not cause denial of service."
            }
          ]
        }
      ],
      "problemTypes": [
        {
          "descriptions": [
            {
              "cweId": "CWE-639",
              "description": "CWE-639 Authorization Bypass Through User-Controlled Key",
              "lang": "en",
              "type": "CWE"
            },
            {
              "cweId": "CWE-522",
              "description": "CWE-522 Insufficiently Protected Credentials",
              "lang": "en",
              "type": "CWE"
            }
          ]
        }
      ],
      "providerMetadata": {
        "dateUpdated": "2026-07-31T15:59:47.841Z",
        "orgId": "f86ef6dc-4d3a-42ad-8f28-e6d5547a5007",
        "shortName": "PostgreSQL"
      },
      "references": [
        {
          "tags": [
            "issue-tracking"
          ],
          "url": "https://github.com/pgadmin-org/pgadmin4/issues/10200"
        },
        {
          "tags": [
            "related"
          ],
          "url": "https://github.com/pgadmin-org/pgadmin4/commit/a7e74a6ed685bc34e1f77a8b6a94d00fa3dff815"
        },
        {
          "tags": [
            "patch"
          ],
          "url": "https://github.com/pgadmin-org/pgadmin4/commit/64a9cdbd6a240a962144f84418beaf9e66419779"
        }
      ],
      "source": {
        "discovery": "INTERNAL"
      },
      "title": "pgAdmin 4: Adhoc server clone leaks another user\u0027s stored database credentials and ownership to a non-owner"
    }
  },
  "cveMetadata": {
    "assignerOrgId": "f86ef6dc-4d3a-42ad-8f28-e6d5547a5007",
    "assignerShortName": "PostgreSQL",
    "cveId": "CVE-2026-17349",
    "datePublished": "2026-07-31T15:59:47.841Z",
    "dateReserved": "2026-07-25T02:52:56.082Z",
    "dateUpdated": "2026-08-01T03:56:26.176Z",
    "state": "PUBLISHED"
  },
  "dataType": "CVE_RECORD",
  "dataVersion": "5.2",
  "vulnerability-lookup:meta": {
    "vulnrichment": {
      "containers": "{\"adp\": [{\"title\": \"CISA ADP Vulnrichment\", \"metrics\": [{\"other\": {\"type\": \"ssvc\", \"content\": {\"id\": \"CVE-2026-17349\", \"role\": \"CISA Coordinator\", \"options\": [{\"Exploitation\": \"none\"}, {\"Automatable\": \"no\"}, {\"Technical Impact\": \"total\"}], \"version\": \"2.0.3\", \"timestamp\": \"2026-07-31T17:21:38.095146Z\"}}}], \"providerMetadata\": {\"orgId\": \"134c704f-9b21-4f2e-91b3-4a467353bcc0\", \"shortName\": \"CISA-ADP\", \"dateUpdated\": \"2026-07-31T17:21:46.538Z\"}}], \"cna\": {\"title\": \"pgAdmin 4: Adhoc server clone leaks another user\u0027s stored database credentials and ownership to a non-owner\", \"source\": {\"discovery\": \"INTERNAL\"}, \"credits\": [{\"lang\": \"en\", \"type\": \"finder\", \"value\": \"Ashesh Vashi \u003cashesh.vashi@enterprisedb.com\u003e\"}, {\"lang\": \"en\", \"type\": \"remediation developer\", \"value\": \"Ashesh Vashi \u003cashesh.vashi@enterprisedb.com\u003e\"}, {\"lang\": \"en\", \"type\": \"remediation reviewer\", \"value\": \"Kundan Sable \u003ckundan.sable@enterprisedb.com\u003e\"}], \"metrics\": [{\"format\": \"CVSS\", \"cvssV3_1\": {\"scope\": \"CHANGED\", \"version\": \"3.1\", \"baseScore\": 9.6, \"attackVector\": \"NETWORK\", \"baseSeverity\": \"CRITICAL\", \"vectorString\": \"CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N\", \"integrityImpact\": \"HIGH\", \"userInteraction\": \"NONE\", \"attackComplexity\": \"LOW\", \"availabilityImpact\": \"NONE\", \"privilegesRequired\": \"LOW\", \"confidentialityImpact\": \"HIGH\"}, \"scenarios\": [{\"lang\": \"en\", \"value\": \"Threat model: an authenticated, low-privilege pgAdmin user who knows or can enumerate the server id of another user\u0027s (e.g. an administrator\u0027s) shared server row triggers an adhoc connect against it. No special privilege beyond ordinary authenticated access is needed, and no interaction from the victim is required. Scope is Changed: the attacker\u0027s own pgAdmin authorization does not itself grant use of the source user\u0027s stored database credentials, so gaining and using those credentials crosses into another user\u0027s security authority -- specifically the database privileges the source user\u0027s stored credentials confer, which may substantially exceed the attacker\u0027s own. Confidentiality and Integrity are High because the attacker obtains a working, reusable database credential and can use it to read/write whatever the source user\u0027s database role permits. Availability is None: the leak itself does not directly cause denial of service.\"}]}, {\"format\": \"CVSS\", \"cvssV4_0\": {\"version\": \"4.0\", \"baseScore\": 9.3, \"baseSeverity\": \"CRITICAL\", \"vectorString\": \"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:N/SC:H/SI:H/SA:N\"}, \"scenarios\": [{\"lang\": \"en\", \"value\": \"Same reasoning as the CVSS 3.1 entry: an authenticated low-privilege user obtains another user\u0027s stored database credential via server cloning, without any interaction from the victim. VC:H/VI:H for pgAdmin\u0027s own scope (the leaked credential itself); SC:H/SI:H because the credential is then usable against the underlying database server, a subsequent system whose privileges may substantially exceed the attacker\u0027s own. VA:N/SA:N since the leak alone does not cause denial of service.\"}]}], \"affected\": [{\"repo\": \"https://github.com/pgadmin-org/pgadmin4\", \"vendor\": \"pgadmin.org\", \"modules\": [\"Workspaces\"], \"product\": \"pgAdmin 4\", \"versions\": [{\"status\": \"affected\", \"version\": \"9.0\", \"lessThan\": \"9.17\", \"versionType\": \"custom\"}], \"programFiles\": [\"https://github.com/pgadmin-org/pgadmin4/blob/master/web/pgadmin/misc/workspaces/__init__.py\"], \"defaultStatus\": \"unaffected\"}], \"references\": [{\"url\": \"https://github.com/pgadmin-org/pgadmin4/issues/10200\", \"tags\": [\"issue-tracking\"]}, {\"url\": \"https://github.com/pgadmin-org/pgadmin4/commit/a7e74a6ed685bc34e1f77a8b6a94d00fa3dff815\", \"tags\": [\"related\"]}, {\"url\": \"https://github.com/pgadmin-org/pgadmin4/commit/64a9cdbd6a240a962144f84418beaf9e66419779\", \"tags\": [\"patch\"]}], \"descriptions\": [{\"lang\": \"en\", \"value\": \"/misc/workspace/adhoc_connect_server, part of the Workspaces feature introduced in pgAdmin 4 9.0, when passed the id of an existing server, clones that server via Server.clone(), which copies every column from the source row, including user_id, shared, shared_username, and the stored credential fields password, save_password, and tunnel_password. When a non-owner triggered an adhoc connect against another user\u0027s (in practice, typically an administrator\u0027s) shared server, the clone inherited that user\u0027s ownership, shared flag, and stored database credentials verbatim. pgAdmin persisted this cross-tenant, credential-bearing server row before the connection was even attempted, so it survived even when the connection subsequently failed. The non-owner could then open the newly-owned clone and pgAdmin would connect using the source user\u0027s stored database password on the non-owner\u0027s behalf, granting the non-owner use of database credentials -- and whatever database privileges they confer -- that were never their own.\\n\\nFix forces the cloned adhoc record\u0027s ownership fields (user_id, shared, shared_username) and stored credential fields (password, save_password, tunnel_password) to belong to the calling user and be cleared/private before committing, regardless of the source server\u0027s ownership, sharing state, or stored credentials. A regression test asserts that an adhoc connect triggered by a non-owner against another user\u0027s shared server persists a row owned by the caller, not shared, and without the source\u0027s stored credentials.\\n\\nThis issue affects pgAdmin 4: from 9.0 before 9.17.\"}], \"problemTypes\": [{\"descriptions\": [{\"lang\": \"en\", \"type\": \"CWE\", \"cweId\": \"CWE-639\", \"description\": \"CWE-639 Authorization Bypass Through User-Controlled Key\"}, {\"lang\": \"en\", \"type\": \"CWE\", \"cweId\": \"CWE-522\", \"description\": \"CWE-522 Insufficiently Protected Credentials\"}]}], \"providerMetadata\": {\"orgId\": \"f86ef6dc-4d3a-42ad-8f28-e6d5547a5007\", \"shortName\": \"PostgreSQL\", \"dateUpdated\": \"2026-07-31T15:59:47.841Z\"}}}",
      "cveMetadata": "{\"cveId\": \"CVE-2026-17349\", \"state\": \"PUBLISHED\", \"dateUpdated\": \"2026-08-01T03:56:26.176Z\", \"dateReserved\": \"2026-07-25T02:52:56.082Z\", \"assignerOrgId\": \"f86ef6dc-4d3a-42ad-8f28-e6d5547a5007\", \"datePublished\": \"2026-07-31T15:59:47.841Z\", \"assignerShortName\": \"PostgreSQL\"}",
      "dataType": "CVE_RECORD",
      "dataVersion": "5.2"
    }
  }
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Sightings

Author Source Type Date

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or seen somewhere by the user.
  • Confirmed: The vulnerability is confirmed from an analyst perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: This vulnerability was exploited and seen by the user reporting the sighting.
  • Patched: This vulnerability was successfully patched by the user reporting the sighting.
  • Not exploited: This vulnerability was not exploited or seen by the user reporting the sighting.
  • Not confirmed: The user expresses doubt about the veracity of the vulnerability.
  • Not patched: This vulnerability was not successfully patched by the user reporting the sighting.


Loading…

Loading…