Tiếng Việt

All advisories

PostgreSQL 18.7, 17.12, 16.16, 15.20, 14.25: vulnerabilities in one minor release

52 vulnerabilities fixed in a single release; 32 of them run code as the server's operating-system user from any logged-in role — so one SQL injection in a web application is enough to reach them.

Released 2026-11-12 · Postgres 18–14 · postgresql.org/about/news/postgresql-187-1712-1616-1520-1425-and-19-rc-2-released-3442/

Read from postgresql.org on 2026-11-13. This page reads one release. PostgreSQL is not yet a product this site checks version by version: there is no per-branch list, no version box, and rasoat host sees the distro's packages but not a container image.

What happened

52 vulnerabilities in one minor release — an unusually large batch for PostgreSQL, which usually fixes a handful at a time.

43 flaws are in the core, 6 in client tools (pg_dump, pg_restore, pg_basebackup, reindexdb, vacuumdb) and 3 in bundled extensions (plperl, pltcl, dblink, dict_int).

40 reach all five lines; the rest touch only the lines that carry the feature, so do not read 52 as the same number for every line.

32 carry CVSS 8.8: they need a logged-in role, but any role will do, and the result is code as the process's operating-system user.

Only 1 needs no login, and that one affects availability only.

PostgreSQL 14 gets its final release here and is end-of-life: no further security fix will come for that line.

The path in

  • Any role, no superuser needed. A web application connects with its own role; one SQL injection in that application is enough to reach these flaws.
  • A closed port does not remove the risk. The attacker goes through the application, not through port 5432.
  • Client tools count too: pg_restore on an archive you did not produce, pg_dump in tar format piped to psql, pg_basebackup reading a manifest — so cron backup jobs and docker exec are in scope.
  • Extensions: only where plperl, pltcl, dblink or dict_int is installed.
  • PostgreSQL 14: end-of-life, so nothing after this release — for that line the answer is a major upgrade, not a minor one.

Which copy runs

  • Docker and Compose: the image tag is the version. postgres:16 pulled on deploy day stays at that day's minor; a floating tag only helps after docker compose pull and up -d.
  • The distro's package: postgresql-16 from the repository; patch with apt, then restart the cluster.
  • Managed services (RDS, Cloud SQL, Supabase, Neon): the provider patches on its own schedule; SELECT version() shows the build that actually runs.
  • Built from source or from your own image: nobody patches it for you.

Running is not installed

  • apt upgrade replaces files on disk; the postmaster keeps the old binary in memory until it restarts. SELECT version() answers "which build is running"; dpkg -l postgresql-16 does not.
  • With a container, pull only downloads the image; up -d creates the new process. docker ps still shows the old image if you stopped at pull.

The fix for each line

LineFixed inStatus
1818.7Supported
1717.12Supported
1616.16Supported
1515.20Supported
1414.25End of life 2026-11-12

After the upgrade, not only the upgrade

Replacing the binary is enough to fix the code, but this release also has data work. The announcement's Updating section, verbatim, so you can check against it:

All PostgreSQL update releases are cumulative. As with other minor releases, users are not required to dump and reload their database or use pg_upgrade in order to apply this update release; you may simply stop PostgreSQL and update its binaries.

If you suspect that a GIN index is affected by one of the corruption issues fixed in this release, you should reindex it, for example:

REINDEX INDEX your_index_name;

If you use pg_trgm, you should reindex any GiST indexes that use the gist_trgm_ops operator class.

If you see missing chunk number errors when reading a table, you should reindex the table, which also reindexes its TOAST table, for example:

REINDEX TABLE your_table_name;

If you use incremental backups, we recommend taking a new full backup after updating and using it as the basis for subsequent incremental backups.

If you use partitioned tables, the following query finds NOT NULL NO INHERIT constraints on partitioned tables:

SELECT conrelid::regclass, conname
FROM pg_constraint
WHERE contype = 'n' AND connoinherit
AND conrelid IN (SELECT oid FROM pg_class WHERE relkind = 'p');

You can remove unwanted constraints with ALTER TABLE ... DROP CONSTRAINT .... Constraints you want to keep should be repaired with ALTER TABLE ... ALTER CONSTRAINT ... INHERIT, which will fail if any of the table's partitions contain NULL values in that column.

If you have B-tree indexes on bpchar columns (that is, columns declared as bpchar without a length), you should reindex them after updating. Columns declared as char(n) are not affected.

Users who have skipped one or more update releases may need to run additional post-update steps; please see the release notes from earlier versions for details.

For more details, please see the release notes .

If you use pg_trgm for search, the GiST REINDEX is the step most easily missed: search keeps working and quietly returns fewer rows.

The 52 vulnerabilities

Descriptions and CVSS scores are quoted in English from postgresql.org's CVE pages; each row links its page.

CVSSCVESummaryComponent
8.8CVE-2026-116304Parallel RECORD typmod use-after-free executes arbitrary codecore
8.8CVE-2026-116306Composite-type change during field assignment executes arbitrary codecore
8.8CVE-2026-116307plperl prepared-query use-after-free executes arbitrary codecore
8.8CVE-2026-116309plperl blessed-reference type confusion may execute arbitrary codecore
8.8CVE-2026-116314pg_restore executes arbitrary code due to missing non-plain archive validationclient
8.8CVE-2026-116315tsvector_delete() heap buffer overflow executes arbitrary codecore
8.8CVE-2026-116316Security-restricted operations can create types in pg_temp, which later queries of the session findcore
8.8CVE-2026-116317ts_rank_cd() heap buffer overflow may execute arbitrary codecore
8.8CVE-2026-116318pg_dump not-null constraint name allows SQL injectionclient
8.8CVE-2026-116319plperl reentrant return_next() use-after-free executes arbitrary codecore
8.8CVE-2026-116320plperl array and hash conversion use-after-free executes arbitrary codecore
8.8CVE-2026-116323pltcl reentrant result conversion use-after-free executes arbitrary codecore
8.8CVE-2026-116326plperl tied-object exceptions follow stale sigjmp_bufcore
8.8CVE-2026-116328Generation memory context integer wraparound executes arbitrary codecore
8.8CVE-2026-116329Statistics import type confusion executes arbitrary codecore
8.8CVE-2026-116330pg_dump tar restore.sql fails to block psql command injectionclient
8.8CVE-2026-116331Min/max aggregate type confusion executes arbitrary codecore
8.8CVE-2026-116332Portal setup use-after-free executes arbitrary codecore
8.8CVE-2026-116335Commutator or negator result-type confusion executes arbitrary codecore
8.8CVE-2026-116336REINDEX CONCURRENTLY does not block DROP INDEX during index functionscore
8.8CVE-2026-120139Tuple-size integer wraparound executes arbitrary codecore
8.8CVE-2026-120141Materialized set-returning function type confusion executes arbitrary codecore
8.8CVE-2026-120142Dropped-column type confusion executes arbitrary codecore
8.8CVE-2026-120143Transition-table cursor use-after-free executes arbitrary codecore
8.8CVE-2026-120144Type-cache invalidation gap executes arbitrary codecore
8.8CVE-2026-120145Logical replication can write to subscriber system catalogs, executing arbitrary codecore
8.8CVE-2026-120147dblink reentrant disconnect use-after-free executes arbitrary codeextension
8.8CVE-2026-120149FDW batch-insert mismatch executes arbitrary codecore
8.8CVE-2026-120150Expanded-record domain-check use-after-free executes arbitrary codecore
8.8CVE-2026-120151plpgsql record-field type confusion executes arbitrary codecore
8.8CVE-2026-18447Output parameter type confusion executes arbitrary codecore
8.8CVE-2026-6460Type confusion after ALTER ... SET DATA TYPE executes arbitrary codecore
8.1CVE-2026-120148Extended-statistics pseudo-type confusion executes arbitrary codecore
8.1CVE-2026-14661dblink and subscriptions can append to arbitrary filesextension
8CVE-2026-116325reindexdb index name quoting allows SQL injectionclient
7.2CVE-2026-116313vacuumdb --missing-stats-only lets a database owner execute code as the vacuumdb userclient
7.2CVE-2026-120153Extension-script substitutions allow SQL injection through object namescore
7.2CVE-2026-6467Extension script schema mishandling executes arbitrary SQLcore
6.5CVE-2026-116333Parallel B-tree array scan reads beyond array boundscore
5.4CVE-2026-116311DROP OWNED can remove restrictive row security policies from non-owned tablescore
5.4CVE-2026-116312MERGE can place the wrong row in a trigger transition tablecore
5.4CVE-2026-16237INSERT ... ON CONFLICT can read or modify rows despite auto-updatable view WHERE conditioncore
5.3CVE-2026-116322Pre-authentication cancel request can leak a spinlockcore
4.3CVE-2026-116308dict_int reads beyond zero-length tokensextension
4.3CVE-2026-116310COPY error context uses freed field storagecore
4.3CVE-2026-116321Unterminated name value discloses server memorycore
4.3CVE-2026-116327security_barrier analysis can expose hidden values through indirect expressionscore
4.3CVE-2026-120146REASSIGN OWNED bypasses role SET and CREATEDB checkscore
4.3CVE-2026-120152pg_show_all_settings() use-after-free discloses memorycore
4.3CVE-2026-120154INSERT ... ON CONFLICT can read rows despite row security policiescore
3.7CVE-2026-16240pg_basebackup can use backup manifest content as a format stringclient
3.1CVE-2026-116303Foreign key and JSON conversions bypass EXECUTE privilege on cast functionscore

What to do

  • Move the line you run to its fixed release — the table above. A minor update needs no dump and reload.
  • PostgreSQL 14: upgrade the major (pg_upgrade, or dump and restore) to a supported line. The last release of 14 is not a fix.
  • Containers: docker compose pull then up -d, then check SELECT version() inside the container.
  • Managed services: read the build in use; if the provider has not patched, there is no fix on your side, only mitigation in the application.

Check yourself

psql -c 'SELECT version();'

Tells you: the build actually running, not the one installed

psql -c 'SHOW server_version;'

Tells you: the version the server reports

psql -c 'SELECT pg_postmaster_start_time();'

Tells you: when the postmaster started: before the package upgrade means the new binary is not loaded

docker exec <container> psql -U postgres -c 'SELECT version();'

Tells you: the build inside the container, not on the host

apt list --installed 'postgresql-*'

Tells you: the installed packages on Debian or Ubuntu — only half the answer

psql -c '\dx'

Tells you: installed extensions: plperl, pltcl, dblink, dict_int are in this group

Sources

Written from the release announcement and postgresql.org's CVE pages; data read on 2026-11-13. Where they differ, postgresql.org wins.