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

CVE-2026-61817: PostgreSQL pg_partman Extension RCE Vulnerability

CVE-2026-61817 is a remote code execution flaw in PostgreSQL pg_partman extension that allows attackers to execute arbitrary SQL with elevated privileges. This post covers technical details, affected versions, impact, and mitigation.

Published:

CVE-2026-61817 Overview

CVE-2026-61817 is a SQL injection vulnerability [CWE-89] in pg_partman, a PostgreSQL extension that manages partitioned tables by time or ID. Versions prior to 5.5.0 interpolate the writable part_config.time_encoder text value into dynamic SQL without identifier quoting. A role holding the documented partman_user privileges can persist malicious SQL in place of a decoder function name. When maintenance later processes the poisoned row, the injected statement executes with the operation's privileges, which can be the PostgreSQL superuser background-worker role.

Critical Impact

Successful exploitation enables 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 maintenance on text- or UUID-keyed partition sets
  • Environments granting the partman_user role to non-administrative principals

Discovery Timeline

  • 2026-09-18 - CVE-2026-61817 published to NVD
  • 2026-09-24 - Last updated in NVD database

Technical Details for CVE-2026-61817

Vulnerability Analysis

The flaw resides in the run_maintenance(), show_partitions(), show_partition_info(), undo_partition(), and partition_data_time() functions. Each of these routines reads the part_config.time_encoder column and interpolates the value directly into dynamically constructed SQL. Because the interpolation omits identifier quoting through format('%I', ...) or an equivalent guard, arbitrary SQL text stored in that column is parsed and executed at query time.

The part_config table is writable by the partman_user role by design. An attacker holding that role can replace the expected decoder function name with a SQL payload. The row persists across ticks, so background-worker maintenance re-triggers execution on every cycle, allowing the attacker to restore elevated access even after partial cleanup.

Root Cause

The root cause is missing identifier sanitization when composing dynamic SQL statements from user-controlled configuration values. The time_encoder field is treated as a trusted identifier but is populated through standard write privileges granted to partman_user, violating the trust boundary between configuration data and executable SQL.

Attack Vector

Exploitation requires network access to PostgreSQL and authentication as a role with partman_user privileges. The attacker updates part_config to store a crafted time_encoder value. When pg_partman_bgw or an operator invokes an affected function against a text- or UUID-keyed partition set, the payload executes in the security context of the background worker, which is typically the PostgreSQL superuser.

text
// Patch metadata from the pg_partman security release
 {
     "name": "pg_partman",
     "abstract": "Extension to manage partitioned tables by time or ID",
-    "version": "5.4.3",
+    "version": "5.5.0",
     "maintainer": [
         "Keith Fiske <keith@keithf4.com>"
     ],

Source: pg_partman commit ba94055

Stop Remote Code Execution Before It Runs

Singularity™ Endpoint detects and blocks exploit attempts at machine speed, including zero-days and novel attack techniques.

Stop Exploit Attempts

Detection Methods for CVE-2026-61817

Indicators of Compromise

  • Unexpected non-identifier content or SQL keywords stored in part_config.time_encoder.
  • PostgreSQL logs showing statements executed by the pg_partman_bgw background worker that reference objects outside pg_partman's scope.
  • Creation or modification of superuser roles, extensions, or COPY ... PROGRAM calls originating from maintenance ticks.
  • Shell commands or files written by the PostgreSQL service account without a corresponding administrator action.

Detection Strategies

  • Audit part_config rows to confirm each time_encoder value resolves to an existing schema-qualified function and contains no whitespace or punctuation typical of SQL.
  • Enable log_statement = 'ddl' or pgaudit on production clusters and alert on DDL executed by the background-worker role.
  • Baseline invocations of run_maintenance(), show_partitions(), show_partition_info(), undo_partition(), and partition_data_time() and flag anomalies in duration or output size.

Monitoring Recommendations

  • Forward PostgreSQL and OS audit logs to a centralized analytics platform for correlation with role and configuration changes.
  • Monitor for new local users, cron entries, or outbound network connections initiated by the PostgreSQL service account.
  • Track membership changes for the partman_user role and any grants that expose write access to part_config.

How to Mitigate CVE-2026-61817

Immediate Actions Required

  • Upgrade pg_partman to version 5.5.0 on every PostgreSQL instance that loads the extension.
  • Inventory all databases where pg_partman is installed and confirm the extension version with SELECT extversion FROM pg_extension WHERE extname = 'pg_partman';.
  • Review current values in part_config.time_encoder and reset any suspicious entries to a known-good decoder function.
  • Rotate credentials for accounts holding partman_user if compromise is suspected.

Patch Information

The fix is included in pg_partman 5.5.0, which enforces identifier quoting when building dynamic SQL from part_config values. See the GitHub Security Advisory GHSA-gmw2-52wc-258g and the pg_partman v5.5.0 release notes for details.

Workarounds

  • Revoke write access to part_config from any role that does not require it, including members of partman_user.
  • Restrict pg_partman_bgw to databases and partition sets that do not use text- or UUID-based keys until patching is complete.
  • Run pg_partman maintenance under a least-privileged role instead of the default superuser background-worker role.
bash
# Verify installed pg_partman version and restrict part_config writes
psql -c "SELECT extname, extversion FROM pg_extension WHERE extname = 'pg_partman';"
psql -c "REVOKE INSERT, UPDATE ON partman.part_config FROM partman_user;"

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.