Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-17351

CVE-2026-17351: Pgadmin 4 SQL Injection Vulnerability

CVE-2026-17351 is a SQL injection flaw in pgAdmin 4 that allows attackers to bypass transaction controls and execute unauthorized SQL commands. This post explains its impact, affected versions, and mitigation steps.

Published:

CVE-2026-17351 Overview

CVE-2026-17351 is a critical SQL injection vulnerability in pgAdmin 4 that reintroduces the write and remote code execution (RCE) bypass previously tracked as CVE-2026-12045. The flaw lives in the AI Assistant's execute_sql_query tool, where a lexer differential between Python's sqlparse library and PostgreSQL's own parser allows attackers to smuggle additional statements past a read-only guard. An attacker delivers the payload through indirect prompt injection, planting crafted SQL text in any object the AI Assistant may read. The affected code path uses psycopg3's simple query protocol by default, which accepts multi-statement text and executes the smuggled commands.

Critical Impact

Successful exploitation escapes the BEGIN TRANSACTION READ ONLY wrapper and enables arbitrary write operations and RCE against the connected PostgreSQL server.

Affected Products

  • pgAdmin 4 versions 9.13 through 9.16
  • Deployments using the AI Assistant execute_sql_query tool
  • PostgreSQL server connections using default prepare_threshold (None)

Discovery Timeline

  • 2026-07-31 - CVE-2026-17351 published to the National Vulnerability Database (NVD)
  • 2026-08-05 - Last updated in NVD database

Technical Details for CVE-2026-17351

Vulnerability Analysis

The vulnerability is a SQL injection [CWE-89] rooted in a parser differential between sqlparse and PostgreSQL. The AI Assistant validator accepts one statement from sqlparse and wraps it in BEGIN TRANSACTION READ ONLY. PostgreSQL's server-side parser interprets the same text differently and executes multiple statements. The smuggled COMMIT closes the read-only transaction, allowing subsequent DDL or DML to run with the connection user's privileges. Because the delivery vector is indirect prompt injection, any data source the large language model (LLM) may read becomes a viable injection point.

Root Cause

Under PostgreSQL's default standard_conforming_strings = on (default since 9.1), a backslash before a quote is a literal character. sqlparse instead treats the backslash as escaping the quote. A payload such as SELECT '\';COMMIT;CREATE TABLE pwn(x int);SELECT 1 --' therefore validates as a single SELECT while PostgreSQL executes four statements. An initial candidate fix passed prepare=True to psycopg's execute(), but psycopg3's PrepareManager silently ignores the argument when prepare_threshold is None — pgAdmin's default. The connection falls back to the simple query protocol, and the bypass remains.

Attack Vector

Exploitation requires a low-privileged authenticated user and user interaction via the AI Assistant. An attacker seeds the malicious SQL in any object the LLM might read, such as a table comment, column description, or query history entry. When the AI Assistant emits the payload as a tool call to execute_sql_query, PostgreSQL executes the smuggled statements. The corrected patch sets conn.prepare_threshold = 0 on the dedicated read-only connection, forcing the extended query protocol regardless of server configuration.

python
     @abstractmethod
     def execute_2darray(self, query, params=None,
-                        formatted_exception_msg=False):
+                        formatted_exception_msg=False, prepare=None):
         pass

Source: pgAdmin commit ef76102. The patch threads a prepare argument through the driver abstract interface and the psycopg3 connection's __internal_blocking_execute method, enabling the extended query protocol on the read-only connection.

Detection Methods for CVE-2026-17351

Indicators of Compromise

  • Unexpected DDL statements (CREATE, DROP, ALTER) originating from pgAdmin service accounts
  • PostgreSQL server logs showing COMMIT followed by additional statements within a single AI Assistant query
  • Presence of unfamiliar tables, functions, or extensions created shortly after AI Assistant usage
  • Table or column comments containing embedded SQL keywords such as COMMIT, CREATE, or COPY

Detection Strategies

  • Enable PostgreSQL log_statement = 'all' on servers accessed by pgAdmin and alert on multi-statement queries from AI Assistant sessions
  • Inspect pgAdmin audit logs for execute_sql_query tool calls whose text contains backslash-quote sequences
  • Correlate LLM tool invocations with schema-change events in the target database

Monitoring Recommendations

  • Track pgAdmin version inventory and flag any deployment on 9.13 through 9.16
  • Monitor PostgreSQL role activity for privilege-sensitive operations tied to interactive pgAdmin connections
  • Baseline expected AI Assistant query patterns and alert on statements containing ; outside of quoted strings

How to Mitigate CVE-2026-17351

Immediate Actions Required

  • Upgrade pgAdmin 4 to version 9.17 or later, which sets prepare_threshold = 0 on the AI Assistant read-only connection
  • Disable the AI Assistant feature on internet-facing or shared pgAdmin instances until the patch is applied
  • Restrict the PostgreSQL roles used by pgAdmin connections to the minimum privileges required

Patch Information

The corrected fix is delivered in pgAdmin 4 version 9.17 via commit ef76102 and follow-up commit bf47924. See the issue discussion for verification details against PostgreSQL 18.

Workarounds

  • Set the per-server "Prepare threshold" field to 0 in pgAdmin server configuration to force the extended query protocol
  • Remove or restrict access to the AI Assistant tool for users connecting to sensitive databases
  • Sanitize or review database object metadata (comments, descriptions) that the LLM may ingest to remove attacker-controlled SQL fragments
bash
# pgAdmin server definition: set Prepare threshold to 0
# Preferences > Servers > [Server] > Advanced > Prepare threshold: 0
#
# Verify psycopg3 behavior at the connection level:
python -c "import psycopg; c = psycopg.connect('...'); c.prepare_threshold = 0; \
  c.execute(\"SELECT '\\';COMMIT;CREATE TABLE pwn(x int);SELECT 1 --'\")"
# Expected error: cannot insert multiple commands into a prepared statement

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.