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

CVE-2026-61781: PostgreSQL pg_partman Extension SQLI Vulnerability

CVE-2026-61781 is a SQL injection vulnerability in PostgreSQL pg_partman extension that allows privilege escalation to superuser access. This article covers technical details, affected versions, impact analysis, and mitigation strategies.

Published:

CVE-2026-61781 Overview

CVE-2026-61781 is a SQL injection vulnerability in pg_partman, a PostgreSQL extension that manages partitioned tables by time or ID. The create_partition_time() function reads the writable part_config.time_encoder text value and interpolates it without identifier quoting into a dynamically executed SELECT statement. A role holding the documented partman_user INSERT and UPDATE privileges can store arbitrary SQL in place of a function name. When the pg_partman_bgw background worker later creates a child partition for a text- or UUID-keyed set, it executes that SQL with pg_partman_bgw.role privileges, which default to PostgreSQL superuser. The issue is fixed in version 5.5.0.

Critical Impact

Successful exploitation permits database-wide compromise and operating-system command execution as the PostgreSQL service account.

Affected Products

  • pg_partman versions prior to 5.5.0
  • PostgreSQL deployments using pg_partman_bgw with text- or UUID-keyed partition sets
  • PostgreSQL installations where pg_partman_bgw.role defaults to a superuser account

Discovery Timeline

  • 2026-09-18 - CVE-2026-61781 published to NVD
  • 2026-09-23 - Last updated in NVD database

Technical Details for CVE-2026-61781

Vulnerability Analysis

The vulnerability is a SQL injection flaw classified under [CWE-89]. The create_partition_time() function in pg_partman treats the part_config.time_encoder column as a trusted identifier and inlines it directly into dynamic SQL. Because the column is writable by any role granted the documented partman_user INSERT and UPDATE privileges, an attacker can substitute executable SQL for the expected function name.

Exploitation is asynchronous. The malicious payload is executed later by the pg_partman_bgw background worker under pg_partman_bgw.role privileges. In the default configuration this role is a PostgreSQL superuser, so injected SQL runs with full database rights and can invoke functions that reach the operating system.

Root Cause

The root cause is missing identifier quoting during dynamic SQL construction. The time_encoder value is concatenated into a SELECT statement without quote_ident() or equivalent sanitization, allowing stored text to break out of the identifier context and be parsed as SQL.

Attack Vector

An authenticated database role with partman_user INSERT and UPDATE rights writes crafted SQL into part_config.time_encoder. The pg_partman_bgw worker then triggers execution during its next maintenance tick when it creates a child partition for a text- or UUID-keyed set. The persistent configuration row can repeatedly restore elevated access on later ticks, giving the attacker durable superuser control.

text
// Patch metadata from pg_partman.control
-default_version = '5.4.3'
+default_version = '5.5.0'
 comment = 'Extension to manage partitioned tables by time or ID'
 relocatable = false
 superuser = false
// Source: https://github.com/pgpartman/pg_partman/commit/ba9405542acf24dd881845b935cab8b165854361

Detection Methods for CVE-2026-61781

Indicators of Compromise

  • Unexpected non-identifier characters, whitespace, or SQL keywords in part_config.time_encoder values
  • New or modified PostgreSQL roles, extensions, or COPY ... PROGRAM invocations created shortly after pg_partman_bgw maintenance runs
  • Files or processes owned by the PostgreSQL service account that were not created by administrators

Detection Strategies

  • Query part_config and alert on any time_encoder value that is not a bare, quoted identifier or an expected function reference
  • Audit PostgreSQL logs for pg_partman background worker statements containing DDL, CREATE ROLE, or shell-adjacent functions such as pg_read_server_files
  • Track privilege changes attributable to sessions running under pg_partman_bgw.role

Monitoring Recommendations

  • Enable log_statement = 'ddl' or 'all' on hosts running pg_partman and forward logs to a central analytics store
  • Alert on writes to part_config from roles other than trusted administrators
  • Monitor the PostgreSQL service account for child processes and file writes outside the data directory

How to Mitigate CVE-2026-61781

Immediate Actions Required

  • Upgrade pg_partman to version 5.5.0 or later on all PostgreSQL instances
  • Inspect existing part_config rows and normalize any time_encoder value that is not a plain identifier
  • Rotate credentials for any role that had partman_user INSERT or UPDATE access before the upgrade

Patch Information

The fix ships in pg_partman 5.5.0. Review the GitHub Security Advisory GHSA-742w-3j7c-qwvp, the GitHub Release v5.5.0, and the GitHub Commit Details for the specific code changes.

Workarounds

  • Reassign pg_partman_bgw.role to a non-superuser role scoped only to partition maintenance until patching is complete
  • Revoke INSERT and UPDATE on part_config from partman_user and require administrator-mediated configuration changes
  • Temporarily disable the pg_partman_bgw background worker on sets using text or UUID partition keys
bash
# Restrict pg_partman_bgw.role and lock down configuration writes
ALTER SYSTEM SET pg_partman_bgw.role = 'partman_maint';
REVOKE INSERT, UPDATE ON partman.part_config FROM partman_user;
SELECT pg_reload_conf();

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

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.