docs: add pgcrypto legacy-cipher caveat for the 15.19/17.11 upgrade (#49894)

## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

Docs update — follow-up to #49621 for the Postgres 15.19 / 17.11
release.

## What is the current behavior?

The upgrade guide covers three of the four customer-action items for
this release; the pgcrypto legacy-cipher caveat (CVE-2026-14663) was
deliberately held pending Security sign-off on the wording.

## What is the new behavior?

Adds a "Pgcrypto legacy PGP ciphers" section (between the Ltree and
Btree_gist sections, matching the release comms order): who is affected
(`bf`/`blowfish`/`cast5` only), the wrong-key decrypt probe to check
stored data, the AES re-encrypt step (with `ignore-cipher-failure=1` for
post-upgrade recovery), and the secret-rotation recommendation. Wording
approved by Security.

## Additional context

Refs PSQL-1245 / PSQL-1110. Matches the customer email draft and
changelog entry wording.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **Documentation**
- Updated `pgcrypto` upgrade guidance to separate pre-upgrade decryption
from post-upgrade recovery, including the appropriate handling for
cipher failures.
- Added row-based targeting and plaintext spot checks before bulk
updates.
- Clarified that automated wrong-key scans cover symmetric messages;
public-key messages require manual identification and key-pair
re-encryption.
- Updated the caution note to direct users to scan stored values rather
than rely on a fixed list of cipher algorithms. No action is needed when
`cipher-algo` was never specified.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Utkarash Kumar Singh authored and GitHub committed 2026-09-04 13:31:18 +01:00
1 parent d5e8c882c1
commit 3d2148a821
2 files changed
+57

No files matched your search

@@ -286,6 +286,61 @@ Reindex each index it returns, using the schema-qualified name. `REINDEX INDEX C
REINDEX INDEX CONCURRENTLY <schema_name>.<index_name>;
```
### Pgcrypto legacy PGP ciphers
_Applies when upgrading to Postgres 15.19 or 17.11._
<Admonition type="caution">
You are affected only if you call pgcrypto PGP functions with a `cipher-algo` that is unavailable in your server's OpenSSL build. The default cipher (AES) is not affected — if you never pass a `cipher-algo` option, no action is needed. Use the scan below to check stored values.
</Admonition>
This release fixes [CVE-2026-14663](https://www.postgresql.org/support/security/CVE-2026-14663/): previously, when a requested PGP cipher was unavailable in the server's OpenSSL build, pgcrypto did not apply it, so affected values were not protected as intended and can be decrypted even with the wrong key. After upgrading, decrypting such messages fails by default, and encrypting with those ciphers returns an error.
To find affected rows, scan each stored value with a deliberately wrong passphrase: properly encrypted values raise an error, while affected values decrypt successfully even with the wrong key. Run the helper and the scan in the same session (`pg_temp` functions are session-scoped):
```sql
create function pg_temp.affected_by_cve_2026_14663(msg bytea)
returns boolean
language plpgsql as $$
begin
perform pgp_sym_decrypt_bytea(msg, 'deliberately-wrong-key');
return true;
exception when others then
return false;
end $$;
select <id_column>
from <your_table>
where <your_encrypted_column> is not null
and pg_temp.affected_by_cve_2026_14663(<your_encrypted_column>);
```
Any rows returned hold affected values. The scan covers symmetric (`pgp_sym_*`) messages; the wrong-key probe does not apply to public-key (`pgp_pub_*`) messages. If you call `pgp_pub_encrypt` with one of the affected `cipher-algo` options, treat those values as affected and re-encrypt them the same way using `pgp_pub_decrypt` and `pgp_pub_encrypt` with your key pair.
Re-encrypt affected values with a modern cipher. Before you upgrade, the current version still decrypts them normally:
```sql
update <your_table>
set <col> = pgp_sym_encrypt(
pgp_sym_decrypt(<col>, '<your-key>'),
'<your-key>', 'cipher-algo=aes256')
where <id_column> in (/* rows found by the scan above */);
```
After you upgrade, decrypting affected values fails by default — add `ignore-cipher-failure=1` to read them:
```sql
update <your_table>
set <col> = pgp_sym_encrypt(
pgp_sym_decrypt(<col>, '<your-key>', 'ignore-cipher-failure=1'),
'<your-key>', 'cipher-algo=aes256')
where <id_column> in (/* rows found by the scan above */);
```
If the plaintext is binary (encrypted with `pgp_sym_encrypt_bytea`), use `pgp_sym_decrypt_bytea` and `pgp_sym_encrypt_bytea` in the same way — the text functions reject binary plaintext. Spot-check that a recovered value decrypts to the expected plaintext before running the update across all rows. Because affected values were not protected as intended, consider rotating any secrets stored this way.
### Btree_gist indexes on float columns require reindexing after upgrade
_Applies when upgrading to Postgres 15.19 or 17.11._
+2
View File
@@ -350,6 +350,8 @@ allow_list = [
"PGroonga",
"pg_basebackup",
"PgBouncer",
"pgcrypto",
"Pgcrypto",
"pgjwt",
"PHI",
"Pico",