This CVE exposes a second wave of SQL injection in pgAdmin's template rendering — and the root cause is more revealing than the first. The CVE-2026-12044 fix correctly hardened sixteen templates using qtLiteral, but the team maintained an ALLOWLIST that exempted names sourced from pg_catalog (schema, table, publication, and subscription names) under the assumption that PostgreSQL never includes special characters in identifiers. That assumption is architecturally wrong. pg_catalog is not a curated namespace — it mirrors every CREATE statement ever executed. The convention held only as long as no one deliberately violated it. That's security through assumed politeness, not security.

The privilege escalation vector is the critical insight most write-ups will miss. A low-privilege user with CREATE PUBLICATION or CREATE SUBSCRIPTION can inject into a high-privilege user's session by naming an object with a single quote. The attacker never touches their own Statistics or Dependencies tab — they plant the payload and wait. When a DBA later browses the publication or subscription tree, the rendered template executes with the DBA's session context. This inverts the typical injection model where attacker and victim are the same user. The attack surface extends to every privileged user who ever queries that database's catalog, not just the specific object owner.

The fix adds conn=self.conn to render_template calls that were missing the connection context — the escaping requirement lived in the template filter definition but wasn't surfaced at the call site. This affected both pg and ppas/EPAS dialects, indicating the same flawed mental model was copied between backends.

Audit your own deployment: first, identify every render_template call still missing the conn parameter in your pgAdmin codebase. Second, review any remaining ALLOWLIST entries in test_sql_string_literal_lint.py — if any cite runtime environment assumptions (identifier conventions, character restrictions, catalog content), treat them as suspected vulnerabilities rather than audited exceptions. Third, search for other template paths using raw '{{ name }}' interpolation that process user-created object names; the allowlist was only applied to specific file paths, so paths outside those directories may have identical patterns with no protection at all.

The regression test verifies rendered SQL parses as exactly one statement — a strong signal the team now understands the failure mode. But the existence of this CVE raises a process question: the original CVE-2026-12044 fix should have triggered a mandatory audit of every allowlist entry citing runtime environment constraints. It didn't. That organizational gap is the underlying condition that produced this second wave, and it's the same gap that will produce a third if not explicitly addressed.