PostgreSQL 18.6 升级自查:pgcrypto 曾静默把明文 XOR,GIN reltuples 也要检查
PostgreSQL 18.6 发布于 2026-08-13。18.5 在封装完成后发现回归,从未发布——所以版本号是从 18.4 直接跳到 18.6 的。18.X 内部升级不需要 dump/restore,但这次有几条安全修复涉及配置调整和数据清洗,升级前值得逐条过一遍。
逻辑解码输出插件被收进白名单(CVE-2026-6471)
此前复制用户可以在逻辑解码时选择任意可加载库,等于把扩展加载面开放给了复制角色。18.6 起输出插件必须由 output_plugin_libraries 指定,默认只包含 pgoutput 和 test_decoding:
output_plugin_libraries = 'pgoutput, test_decoding, my_trusted_decoder'
用了第三方解码器的实例必须把它们补进这个列表,否则解码会直接失效。另外,从 v17 及以上版本迁移时,如果新集群的 output_plugin_libraries 不允许旧集群逻辑复制槽所用的插件,pg_upgrade --check 会失败——建议在停库前先跑一次检查。
pgcrypto:以前遇到不支持的 cipher 会静默 XOR
contrib/pgcrypto 的 PGP 加密存在一个更隐蔽的问题:当 OpenSSL 拒绝请求的 cipher 时——FIPS 模式,或者 legacy provider 没有加载,例如 cipher-algo=blowfish/bf、twofish、cast5、3des——pgcrypto 不会察觉失败,而是把未加密的数据块直接和明文做 XOR。结果是密文看着正常,实际强度约等于零。
18.6 起默认行为改为解密直接失败。要处理旧数据,得先把明文剥出来再重新加密,为此新增了 ignore-cipher-failure=1 选项,同时作用于 pgp_pub_decrypt() 和 pgp_sym_decrypt():
SELECT pgp_sym_decrypt(encrypted_column, 'your key', 'ignore-cipher-failure=1')
FROM encrypted_table;
剥壳之后用现代算法重新加密存储。注意加解密两端的 OpenSSL 行为必须一致,否则旧数据仍然读不出来。
并行 GIN 索引的 reltuples 与 reindex
并行构建 GIN 索引时 reltuples 可能被写成错误的值,计划器的估算会跟着偏。如果用了 contrib/btree_gist 或 contrib/ltree,相关索引需要重建:
REINDEX INDEX CONCURRENTLY idx_name;
tzdata 2026c
时区数据同步到 tzdata 2026c。其中一个变化是摩洛哥 Africa/Casablanca:自 2026-09-20 起永久使用 UTC+1,不再切换夏令时。有按当地时间调度的任务需要确认一下。