PostgreSQL 18.7, 17.12, 16.16, 15.20, 14.25: lỗ hổng trong một bản cập nhật nhỏ
52 lỗ hổng được vá trong cùng một lần; 32 lỗi trong số đó cho phép chạy mã bằng user hệ điều hành của máy chủ, từ một role đã đăng nhập bất kỳ — nên một lỗ SQL injection trong ứng dụng web là đủ để chạm tới.
Đọc từ postgresql.org ngày 13/11/2026. Trang này đọc đúng một bản phát hành. PostgreSQL chưa phải sản phẩm được kiểm tra từng phiên bản trên trang này: không có danh sách theo nhánh, không có ô kiểm tra phiên bản, và rasoat host chỉ thấy gói của bản phân phối — không thấy image container.
Chuyện gì xảy ra
52 lỗ hổng trong một bản cập nhật nhỏ — con số lớn bất thường với PostgreSQL, vốn thường vá vài lỗi mỗi lần.
43 lỗi nằm trong lõi, 6 ở công cụ client (pg_dump, pg_restore, pg_basebackup, reindexdb, vacuumdb) và 3 ở extension đóng gói kèm (plperl, pltcl, dblink, dict_int).
40 lỗi chạm tới cả năm nhánh; số còn lại chỉ chạm những nhánh đã có tính năng liên quan, nên đừng đọc con số 52 như nhau cho mọi nhánh.
32 lỗi có CVSS 8.8: cần một role đã đăng nhập, nhưng role nào cũng được, và kết quả là chạy mã bằng user hệ điều hành của tiến trình.
Chỉ 1 lỗi không cần đăng nhập, và lỗi đó chỉ ảnh hưởng tính sẵn sàng.
PostgreSQL 14 nhận bản cuối cùng trong đợt này và hết hỗ trợ: sau đó không còn bản vá bảo mật nào cho nhánh đó.
Đường vào
- Một role bất kỳ, không cần superuser. Ứng dụng web kết nối bằng role riêng của nó; một lỗ SQL injection ở ứng dụng là đủ để chạm tới các lỗi này.
- Cổng 5432 không mở ra internet không làm mất rủi ro. Kẻ tấn công đi qua ứng dụng, không đi qua cổng.
- Công cụ client cũng là bề mặt:
pg_restoretrên một archive không phải do bạn tạo,pg_dumpđịnh dạng tar rồi đưa chopsql,pg_basebackupđọc manifest — nên cron backup vàdocker execcũng nằm trong phạm vi. - Extension: chỉ khi đã cài
plperl,pltcl,dblinkhoặcdict_int. - PostgreSQL 14: đã hết hỗ trợ, nên sau bản này không còn bản vá — với nhánh đó, câu trả lời là nâng major, không phải nâng minor.
Bản nào đang chạy
- Docker và Compose: thẻ image chính là phiên bản.
postgres:16kéo về hôm deploy vẫn là bản minor của hôm đó; thẻ trôi chỉ có tác dụng saudocker compose pullrồiup -d. - Gói của bản phân phối:
postgresql-16từ kho; vá bằngapt, rồi khởi động lại cluster. - Dịch vụ quản lý (RDS, Cloud SQL, Supabase, Neon): nhà cung cấp vá theo lịch của họ;
SELECT version()cho biết bản thật đang chạy. - Tự biên dịch hoặc image tự dựng: không có ai vá hộ.
Đang chạy, không phải đã cài
apt upgradethay tệp trên đĩa; postmaster vẫn giữ binary cũ trong bộ nhớ tới khi khởi động lại.SELECT version()trả lời câu hỏi “đang chạy bản nào”;dpkg -l postgresql-16thì không.- Với container,
pullchỉ tải image;up -dmới tạo tiến trình mới.docker psvẫn hiện image cũ nếu bạn chỉ pull.
Bản vá cho từng nhánh
| Nhánh | Bản vá | Trạng thái |
|---|---|---|
| 18 | 18.7 | Còn hỗ trợ |
| 17 | 17.12 | Còn hỗ trợ |
| 16 | 16.16 | Còn hỗ trợ |
| 15 | 15.20 | Còn hỗ trợ |
| 14 | 14.25 | Hết hỗ trợ 12/11/2026 |
Sau khi nâng cấp, không chỉ nâng cấp
Thay binary là đủ để vá, nhưng đợt này còn việc phải làm trên dữ liệu. Nguyên văn mục Updating của thông báo phát hành, để bạn đối chiếu:
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 .
Nếu dùng pg_trgm cho tìm kiếm, bước REINDEX GiST là bước dễ bị bỏ sót nhất: tìm kiếm vẫn chạy nhưng trả thiếu dòng.
Danh sách 52 lỗ hổng
Mô tả và điểm CVSS giữ nguyên tiếng Anh từ trang CVE của postgresql.org; mỗi dòng dẫn về trang đó.
| CVSS | CVE | Tóm tắt | Thành phần |
|---|---|---|---|
| 8.8 | CVE-2026-116304 | Parallel RECORD typmod use-after-free executes arbitrary code | lõi |
| 8.8 | CVE-2026-116306 | Composite-type change during field assignment executes arbitrary code | lõi |
| 8.8 | CVE-2026-116307 | plperl prepared-query use-after-free executes arbitrary code | lõi |
| 8.8 | CVE-2026-116309 | plperl blessed-reference type confusion may execute arbitrary code | lõi |
| 8.8 | CVE-2026-116314 | pg_restore executes arbitrary code due to missing non-plain archive validation | client |
| 8.8 | CVE-2026-116315 | tsvector_delete() heap buffer overflow executes arbitrary code | lõi |
| 8.8 | CVE-2026-116316 | Security-restricted operations can create types in pg_temp, which later queries of the session find | lõi |
| 8.8 | CVE-2026-116317 | ts_rank_cd() heap buffer overflow may execute arbitrary code | lõi |
| 8.8 | CVE-2026-116318 | pg_dump not-null constraint name allows SQL injection | client |
| 8.8 | CVE-2026-116319 | plperl reentrant return_next() use-after-free executes arbitrary code | lõi |
| 8.8 | CVE-2026-116320 | plperl array and hash conversion use-after-free executes arbitrary code | lõi |
| 8.8 | CVE-2026-116323 | pltcl reentrant result conversion use-after-free executes arbitrary code | lõi |
| 8.8 | CVE-2026-116326 | plperl tied-object exceptions follow stale sigjmp_buf | lõi |
| 8.8 | CVE-2026-116328 | Generation memory context integer wraparound executes arbitrary code | lõi |
| 8.8 | CVE-2026-116329 | Statistics import type confusion executes arbitrary code | lõi |
| 8.8 | CVE-2026-116330 | pg_dump tar restore.sql fails to block psql command injection | client |
| 8.8 | CVE-2026-116331 | Min/max aggregate type confusion executes arbitrary code | lõi |
| 8.8 | CVE-2026-116332 | Portal setup use-after-free executes arbitrary code | lõi |
| 8.8 | CVE-2026-116335 | Commutator or negator result-type confusion executes arbitrary code | lõi |
| 8.8 | CVE-2026-116336 | REINDEX CONCURRENTLY does not block DROP INDEX during index functions | lõi |
| 8.8 | CVE-2026-120139 | Tuple-size integer wraparound executes arbitrary code | lõi |
| 8.8 | CVE-2026-120141 | Materialized set-returning function type confusion executes arbitrary code | lõi |
| 8.8 | CVE-2026-120142 | Dropped-column type confusion executes arbitrary code | lõi |
| 8.8 | CVE-2026-120143 | Transition-table cursor use-after-free executes arbitrary code | lõi |
| 8.8 | CVE-2026-120144 | Type-cache invalidation gap executes arbitrary code | lõi |
| 8.8 | CVE-2026-120145 | Logical replication can write to subscriber system catalogs, executing arbitrary code | lõi |
| 8.8 | CVE-2026-120147 | dblink reentrant disconnect use-after-free executes arbitrary code | extension |
| 8.8 | CVE-2026-120149 | FDW batch-insert mismatch executes arbitrary code | lõi |
| 8.8 | CVE-2026-120150 | Expanded-record domain-check use-after-free executes arbitrary code | lõi |
| 8.8 | CVE-2026-120151 | plpgsql record-field type confusion executes arbitrary code | lõi |
| 8.8 | CVE-2026-18447 | Output parameter type confusion executes arbitrary code | lõi |
| 8.8 | CVE-2026-6460 | Type confusion after ALTER ... SET DATA TYPE executes arbitrary code | lõi |
| 8.1 | CVE-2026-120148 | Extended-statistics pseudo-type confusion executes arbitrary code | lõi |
| 8.1 | CVE-2026-14661 | dblink and subscriptions can append to arbitrary files | extension |
| 8 | CVE-2026-116325 | reindexdb index name quoting allows SQL injection | client |
| 7.2 | CVE-2026-116313 | vacuumdb --missing-stats-only lets a database owner execute code as the vacuumdb user | client |
| 7.2 | CVE-2026-120153 | Extension-script substitutions allow SQL injection through object names | lõi |
| 7.2 | CVE-2026-6467 | Extension script schema mishandling executes arbitrary SQL | lõi |
| 6.5 | CVE-2026-116333 | Parallel B-tree array scan reads beyond array bounds | lõi |
| 5.4 | CVE-2026-116311 | DROP OWNED can remove restrictive row security policies from non-owned tables | lõi |
| 5.4 | CVE-2026-116312 | MERGE can place the wrong row in a trigger transition table | lõi |
| 5.4 | CVE-2026-16237 | INSERT ... ON CONFLICT can read or modify rows despite auto-updatable view WHERE condition | lõi |
| 5.3 | CVE-2026-116322 | Pre-authentication cancel request can leak a spinlock | lõi |
| 4.3 | CVE-2026-116308 | dict_int reads beyond zero-length tokens | extension |
| 4.3 | CVE-2026-116310 | COPY error context uses freed field storage | lõi |
| 4.3 | CVE-2026-116321 | Unterminated name value discloses server memory | lõi |
| 4.3 | CVE-2026-116327 | security_barrier analysis can expose hidden values through indirect expressions | lõi |
| 4.3 | CVE-2026-120146 | REASSIGN OWNED bypasses role SET and CREATEDB checks | lõi |
| 4.3 | CVE-2026-120152 | pg_show_all_settings() use-after-free discloses memory | lõi |
| 4.3 | CVE-2026-120154 | INSERT ... ON CONFLICT can read rows despite row security policies | lõi |
| 3.7 | CVE-2026-16240 | pg_basebackup can use backup manifest content as a format string | client |
| 3.1 | CVE-2026-116303 | Foreign key and JSON conversions bypass EXECUTE privilege on cast functions | lõi |
Cách xử lý
- Nâng đúng nhánh đang chạy lên bản vá của nhánh đó — bảng ở trên. Bản cập nhật nhỏ không cần dump và reload.
- PostgreSQL 14: nâng major (
pg_upgrade, hoặc dump rồi restore) sang nhánh còn hỗ trợ. Bản cuối của nhánh 14 không phải là bản vá. - Container:
docker compose pullrồiup -d, sau đó kiểm traSELECT version()bên trong container. - Dịch vụ quản lý: đọc bản đang chạy; nếu nhà cung cấp chưa vá thì bên bạn không có cách vá, chỉ còn giảm thiểu ở tầng ứng dụng.
Tự kiểm tra
psql -c 'SELECT version();'Cho biết: bản đang chạy thật, không phải bản đã cài
psql -c 'SHOW server_version;'Cho biết: số phiên bản server trả lời
psql -c 'SELECT pg_postmaster_start_time();'Cho biết: thời điểm postmaster khởi động: trước lúc nâng gói nghĩa là chưa nạp binary mới
docker exec <container> psql -U postgres -c 'SELECT version();'Cho biết: bản trong container, không phải trên máy chủ
apt list --installed 'postgresql-*'Cho biết: gói đã cài trên Debian/Ubuntu — chỉ là nửa câu trả lời
psql -c '\dx'Cho biết: extension đã cài: plperl, pltcl, dblink, dict_int nằm trong nhóm lỗi này
Nguồn
- https://www.postgresql.org/about/news/postgresql-187-1712-1616-1520-1425-and-19-rc-2-released-3442/
- https://www.postgresql.org/support/security/
- CVE-2026-116304
- CVE-2026-116306
- CVE-2026-116307
Viết từ thông báo phát hành và trang CVE của postgresql.org; dữ liệu đọc ngày 13/11/2026. Khi có khác biệt, postgresql.org là chuẩn.