CVE-2026-61820
Executive Summary
CVE-2026-61820 is an SQL injection vulnerability in pg_partman, a widely deployed PostgreSQL extension that automates time- and ID-based table partitioning. Prior to version 5.5.0, the inherit_template_properties() function fails to escape embedded double-quote characters when quoting primary-key column names drawn from pg_attribute.attname, allowing a partman_user who owns a template table to inject arbitrary SQL. Because the crafted identifier is later applied by the background worker under the pg_partman_bgw.role — which defaults to a PostgreSQL superuser — successful exploitation enables database-wide compromise and operating-system command execution as the PostgreSQL service account, scoring CVSS 8.5 (High).
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.
No signup required
Technical Analysis
pg_partman manages partitioned tables by automating the creation and maintenance of child partitions based on time or ID ranges. A background worker process (pg_partman_bgw) periodically executes maintenance logic, including propagation of template-table properties — such as primary keys — to newly created child partitions.
The vulnerability resides in inherit_template_properties(). According to the NVD description, this function "manually surrounds primary-key column names from pg_attribute.attname with double quotes without escaping embedded double-quote characters." In SQL identifier quoting, a literal double-quote inside a quoted identifier must be escaped by doubling it (e.g., " becomes ""). The function omits this escaping step. Consequently, a column name that itself contains a double-quote character can terminate the quoted identifier prematurely and inject arbitrary SQL tokens into the statement that is subsequently assembled.
The flaw is classified as CWE-89 (SQL Injection) and, more precisely, represents an improper neutralization of special elements in an SQL command via a catalog-derived identifier. The attack surface is reached by a user with the partman_user role who owns a template table. Such a user can define a column whose name embeds a double-quote sequence, which is stored verbatim in pg_attribute.attname. When the background worker later reads that stored identifier and wraps it in double quotes without escaping, the resulting ALTER TABLE ... ADD PRIMARY KEY ... statement — as described in the advisory — breaks out of the intended identifier context and executes attacker-controlled SQL.
Two factors elevate the severity:
- Privilege context of execution. The generated SQL runs under
pg_partman_bgw.role, which by default maps to a PostgreSQL superuser. A low-privilegedpartman_usertherefore achieves privilege escalation to superuser through a confused-deputy pattern: the worker executes SQL that the attacker influenced but did not directly author. - Persistence and re-triggering. The crafted catalog identifier persists in
pg_attributeuntil explicitly removed. Per the advisory, it "can trigger again during later partition creation," meaning remediation of a single injected statement is insufficient if the malicious column name remains in the catalog.
Impact includes database-wide compromise (arbitrary SQL under superuser) and operating-system command execution as the PostgreSQL service account (for example, via superuser file-write or command-utility primitives in PostgreSQL). The scope change (S:C) in the CVSS vector reflects the transition from the partman_user's security scope to that of the superuser worker.
No public proof-of-concept, Nuclei template, or exploit code has been observed, and EPSS has not yet scored this CVE. The mechanism nevertheless follows a well-understood injection pattern, and the description is specific enough to reconstruct the attack chain at the class level.
Exploitation Scenarios
No public PoC is available; the following attack chain is inferred from the vulnerability class and the NVD description. Specific code patterns, injected statements, and function names beyond those in the description are deliberately not fabricated.
Reconnaissance / target identification. The attacker identifies a PostgreSQL instance with pg_partman < 5.5.0 installed and a partitioned table whose management is delegated to a role holding
partman_userprivileges. The attacker must possess, or be able to obtain, ownership of the relevant template table, sinceinherit_template_properties()operates on template-derived properties.Triggering the flaw class. The attacker (as
partman_userand template-table owner) creates a crafted column name that embeds a double-quote character. This name is persisted intopg_attribute.attname. When the background worker invokesinherit_template_properties()to apply primary-key properties to a child partition, the function quotes the column name without escaping the embedded double-quote, breaking out of the generatedALTER TABLE ... ADD PRIMARY KEYidentifier context. The precise injected SQL is attacker-supplied and thus not fixed; the class is identifier-based SQL injection.Payload / execution. The generated SQL is assembled and executed by the background worker under
pg_partman_bgw.roleprivileges, which default to PostgreSQL superuser. Because execution occurs in this elevated context, the attacker's injected SQL runs with superuser authority, enabling arbitrary database operations and, through standard PostgreSQL superuser capabilities, operating-system command execution as the service account.Post-exploitation impact. With superuser-level execution, the attacker can read or modify arbitrary database contents, create persistent database objects or roles, exfiltrate sensitive data, and execute OS commands as the PostgreSQL service account. Because the crafted catalog identifier persists in
pg_attributeuntil removed, the injection can re-trigger during subsequent partition creations, providing a repeatable, persistent foothold unless the malicious identifier is explicitly cleaned up and the function is upgraded.
Impact Assessment
- Confidentiality: High. Superuser-level SQL execution exposes all data in the database cluster, including tables the attacker had no prior authorization to read.
- Integrity: High. The attacker can modify or delete data, alter schema, and create persistent objects under superuser authority.
- Availability: High. Superuser access allows destructive operations (dropping objects, locking/blocking workloads, or causing service disruption).
- Scope: Changed. The partman_user's scope is bypassed; the impact propagates to the superuser context of the background worker (AV:N/AC:H/PR:L/UI:N/S:C). The High attack complexity reflects prerequisites such as template-table ownership and the presence of an active background worker.
Blast radius. Any PostgreSQL deployment running pg_partman < 5.5.0 with the default superuser-mapped background worker role is affected. Compromise of the worker context potentially exposes every database and every object in the cluster, as well as the underlying host filesystem and OS-level capabilities reachable by the PostgreSQL service account. Even without reaching OS execution, the database-wide data exposure is material for regulated or multi-tenant environments.
Business impact. For managed database providers, multi-tenant SaaS platforms, and enterprises with shared PostgreSQL clusters, exploitation constitutes a full-cluster breach with potential regulatory, financial, and reputational consequences. The persistence of the injected identifier means that point-in-time cleanup of a single SQL statement is inadequate — a re-trigger during routine partition maintenance can re-establish the foothold.
Detection Guidance
Sigma Rule
title: Suspicious pg_partman Background Worker SQL Execution (CVE-2026-61820)
id: 8f2b1c7a-6d4e-4b9f-9a1c-3e5d7f0a2b44
status: experimental
description: Detects suspicious PostgreSQL log entries indicative of SQL injection
via unescaped identifiers in pg_partman inherit_template_properties() prior to 5.5.0.
references:
- https://nvd.nist.gov/vuln/detail/CVE-2026-61820
author: Valters IT Threat Intelligence
date: 2026/01/01
logsource:
product: postgresql
service: postgresql
detection:
selection_worker:
- 'pg_partman_bgw'
- 'partman_user'
selection_injection:
- 'ALTER TABLE'
- 'ADD PRIMARY KEY'
- '""'
condition: all of selection_*
level: high
tags:
- attack.t1190
- cwe.cwe-89
YARA Rule
rule CVE_2026_61820_pg_partman_identifier_injection
{
meta:
author = "Valters IT Threat Intelligence"
description = "Detects pg_partman SQL injection artifacts from unescaped double-quote identifiers (CVE-2026-61820)"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2026-61820"
date = "2026-01-01"
severity = "high"
strings:
$fn = "inherit_template_properties" ascii
$t1 = "ALTER TABLE" ascii
$t2 = "ADD PRIMARY KEY" ascii
$bgw = "pg_partman_bgw" ascii
$attr = "pg_attribute" ascii
$esc = "\"\"" ascii
condition:
uint16(0) == 0x0A0A or true
and $fn
and any of ($bgw, $attr, $esc)
and any of ($t1, $t2)
}
Suricata IDS Rule
alert tcp $HOME_NET any -> $HOME_NET 5432 (msg:"CVE-2026-61820 pg_partman SQL injection via unescaped identifier in ALTER TABLE ADD PRIMARY KEY"; flow:to_server,established; content:"ALTER TABLE"; nocase; content:"ADD PRIMARY KEY"; nocase; content:"inherit_template_properties"; nocase; reference:cve,2026-61820; classtype:attempted-admin; sid:2026618201; rev:1;)
Elastic Detection
sequence by host.name, process.pid with maxspan=5m
[process where event.action == "start" and process.name : "postgres*"]
[file where process.name : "postgres*" and file.path : "*pg_partman*"]
Splunk SPL Query
index=postgres (source=postgresql OR source=postgres)
| search ("pg_partman_bgw" OR "partman_user" OR "inherit_template_properties")
| search ("ALTER TABLE" AND "ADD PRIMARY KEY" AND "\"\"")
| stats count min(_time) as first_seen max(_time) as last_seen by host, source, sourcetype
| where count > 0
| convert ctime(first_seen) ctime(last_seen)
| sort - count
Wazuh OSSEC Rule
<group name="postgresql,cve-2026-61820,">
<rule id="20261820" level="12">
<decoded_as>postgresql</decoded_as>
<match>inherit_template_properties|pg_partman_bgw</match>
<regex type="pcre2">ALTER\s+TABLE.*ADD\s+PRIMARY\s+KEY</regex>
<description>CVE-2026-61820: Suspected pg_partman SQL injection via unescaped identifier executed by background worker.</description>
<mitre>
<id>T1190</id>
</mitre>
<group>cwe_89,sql_injection,</group>
</rule>
</group>
Mitigation & Patch Guidance
Patch confidence: 0/4 (UNPATCHED — no patch evidence from any tracked source). No vendor fix or workaround is recorded in the provided data. The description nonetheless states the issue "is fixed in version 5.5.0," so upgrading to pg_partman >= 5.5.0 is the definitive remediation. Until an authoritative vendor release is confirmed, apply defense-in-depth controls.
Immediate mitigations
- Restrict
partman_usermembership and template-table ownership to fully trusted roles only. The vulnerability requires template-table ownership; removing that capability from untrusted users breaks the prerequisite. - Do not map
pg_partman_bgw.roleto a PostgreSQL superuser. Run the background worker under a least-privilege role scoped to only the partitioned tables it must maintain. This directly removes the privilege-escalation and OS-command-execution impact even if injection remains possible. - Audit
pg_attribute.attname(and dependent objects) across partitioned schemas for column names containing embedded double-quote characters; remove any such crafted identifiers after a documented cleanup, since persistence allows re-triggering during later partition creation.
- Restrict
Patch / upgrade steps
- Upgrade pg_partman to >= 5.5.0 once the vendor release is available through your PostgreSQL package channel.
- After upgrading, re-scan catalogs for malicious identifiers and confirm the background worker runs under a non-superuser role.
- Validate that partition maintenance jobs complete cleanly and review logs for anomalous
ALTER TABLEstatements.
Long-term hardening
- Enforce least privilege across all extension background workers; never default worker roles to superuser.
- Adopt allow-listing/validation for DDL-derived identifiers and monitor for unescaped identifier patterns in extension code.
- Deploy the detection rules above into the SIEM/EDR stack and alert on catalog modifications to
pg_attributethat introduce quote characters. - Track CVE-2026-61820 for EPSS scoring, vendor advisories, and CISA KEV updates.
References
- NVD — CVE-2026-61820: https://nvd.nist.gov/vuln/detail/CVE-2026-61820
- CWE-89 (Improper Neutralization of Special Elements used in an SQL Command): https://cwe.mitre.org/data/definitions/89.html
- pg_partman project (PostgreSQL partitioning extension): https://github.com/pgpartman/pg_partman
- CVSS v3.1 Specification (scope change / privileged worker context): https://www.first.org/cvss/specification-document
Threat actor campaigns / exploit-in-the-wild evidence: None identified at time of writing. No public PoC, no Nuclei template, no exploit code, and CISA KEV status is NO. EPSS has not yet scored this CVE.
What is this? Security researchers use these exact search queries on Shodan.io (a search engine for internet-connected devices) to find vulnerable systems globally. You can copy these dorks to see if your organization's IP space is exposed.