From 6538e2cbcc94d99eba9e4cb453f40fe67bc77082 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rton=20Boros?= Date: Fri, 26 Jun 2026 11:03:18 +0300 Subject: [PATCH] feat: enable customer installation of amcheck (PSQL-1327) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit amcheck was in supautils' "may be unsafe" list based on upstream PostgreSQL's general caution around physical data structure exposure in error messages. No Supabase-specific exploit was ever documented. The restriction created a support gap: customers hit corrupted indexes after 15→17 upgrades and could not use bt_index_check() to enumerate and fix individual indexes, forcing full REINDEX DATABASE instead. Move amcheck from the superuser-only list to privileged_extensions so customers can install it. Update nix/tests/prime.sql and prime-superuser.sql to match. Co-Authored-By: Claude Sonnet 4.6 --- ansible/files/postgresql_config/supautils.conf.j2 | 4 ++-- nix/tests/prime-superuser.sql | 9 ++++----- nix/tests/prime.sql | 3 ++- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ansible/files/postgresql_config/supautils.conf.j2 b/ansible/files/postgresql_config/supautils.conf.j2 index 58739905e..3c32cc190 100644 --- a/ansible/files/postgresql_config/supautils.conf.j2 +++ b/ansible/files/postgresql_config/supautils.conf.j2 @@ -2,12 +2,12 @@ supautils.extensions_parameter_overrides = '{"pg_cron":{"schema":"pg_catalog"}}' supautils.policy_grants = '{"postgres":["auth.audit_log_entries","auth.flow_state","auth.identities","auth.instances","auth.mfa_amr_claims","auth.mfa_challenges","auth.mfa_factors","auth.oauth_clients","auth.one_time_tokens","auth.refresh_tokens","auth.saml_providers","auth.saml_relay_states","auth.sessions","auth.sso_domains","auth.sso_providers","auth.users","realtime.messages","realtime.subscription","storage.buckets","storage.buckets_analytics","storage.objects","storage.prefixes","storage.s3_multipart_uploads","storage.s3_multipart_uploads_parts"]}' supautils.drop_trigger_grants = '{"postgres":["auth.audit_log_entries","auth.flow_state","auth.identities","auth.instances","auth.mfa_amr_claims","auth.mfa_challenges","auth.mfa_factors","auth.oauth_clients","auth.one_time_tokens","auth.refresh_tokens","auth.saml_providers","auth.saml_relay_states","auth.sessions","auth.sso_domains","auth.sso_providers","auth.users","realtime.messages","realtime.subscription","storage.buckets","storage.buckets_analytics","storage.objects","storage.prefixes","storage.s3_multipart_uploads","storage.s3_multipart_uploads_parts"]}' # full list: address_standardizer, address_standardizer_data_us, adminpack, amcheck, autoinc, bloom, btree_gin, btree_gist, citext, cube, dblink, dict_int, dict_xsyn, earthdistance, file_fdw, fuzzystrmatch, hstore, http, hypopg, index_advisor, insert_username, intagg, intarray, isn, lo, ltree, moddatetime, old_snapshot, orioledb, pageinspect, pg_buffercache, pg_cron, pg_freespacemap, pg_graphql, pg_hashids, pg_jsonschema, pg_net, pg_prewarm, pg_repack, pg_stat_monitor, pg_stat_statements, pg_surgery, pg_tle, pg_trgm, pg_visibility, pg_walinspect, pgaudit, pgcrypto, pgjwt, pgmq, pgroonga, pgroonga_database, pgrouting, pgrowlocks, pgsodium, pgstattuple, pgtap, plcoffee, pljava, plls, plpgsql, plpgsql_check, plv8, postgis, postgis_raster, postgis_sfcgal, postgis_tiger_geocoder, postgis_topology, postgres_fdw, refint, rum, seg, sslinfo, supabase_vault, supautils, tablefunc, tcn, timescaledb, tsm_system_rows, tsm_system_time, unaccent, uuid-ossp, vector, wrappers, xml2 -# omitted because may be unsafe: adminpack, amcheck, file_fdw, lo, old_snapshot, pageinspect, pg_freespacemap, pg_surgery, pg_visibility +# omitted because may be unsafe: adminpack, file_fdw, lo, old_snapshot, pageinspect, pg_freespacemap, pg_surgery, pg_visibility # omitted because deprecated: intagg, xml2 # omitted because doesn't require superuser: pgmq # omitted because protected: plpgsql # NOTE: keep nix/tests/prime-superuser.sql in sync with the "may be unsafe" + "deprecated" lists above. -supautils.privileged_extensions = 'address_standardizer, address_standardizer_data_us, autoinc, bloom, btree_gin, btree_gist, citext, cube, dblink, dict_int, dict_xsyn, earthdistance, fuzzystrmatch, hstore, http, hypopg, index_advisor, insert_username, intarray, isn, ltree, moddatetime, orioledb, pg_buffercache, pg_cron, pg_graphql, pg_hashids, pg_jsonschema, pg_net, pg_prewarm, pg_repack, pg_stat_monitor, pg_stat_statements, pg_tle, pg_trgm, pg_walinspect, pgaudit, pgcrypto, pgjwt, pgroonga, pgroonga_database, pgrouting, pgrowlocks, pgsodium, pgstattuple, pgtap, plcoffee, pljava, plls, plpgsql_check, plv8, postgis, postgis_raster, postgis_sfcgal, postgis_tiger_geocoder, postgis_topology, postgres_fdw, refint, rum, seg, sslinfo, supabase_vault, supautils, tablefunc, tcn, timescaledb, tsm_system_rows, tsm_system_time, unaccent, uuid-ossp, vector, wrappers' +supautils.privileged_extensions = 'address_standardizer, address_standardizer_data_us, amcheck, autoinc, bloom, btree_gin, btree_gist, citext, cube, dblink, dict_int, dict_xsyn, earthdistance, fuzzystrmatch, hstore, http, hypopg, index_advisor, insert_username, intarray, isn, ltree, moddatetime, orioledb, pg_buffercache, pg_cron, pg_graphql, pg_hashids, pg_jsonschema, pg_net, pg_prewarm, pg_repack, pg_stat_monitor, pg_stat_statements, pg_tle, pg_trgm, pg_walinspect, pgaudit, pgcrypto, pgjwt, pgroonga, pgroonga_database, pgrouting, pgrowlocks, pgsodium, pgstattuple, pgtap, plcoffee, pljava, plls, plpgsql_check, plv8, postgis, postgis_raster, postgis_sfcgal, postgis_tiger_geocoder, postgis_topology, postgres_fdw, refint, rum, seg, sslinfo, supabase_vault, supautils, tablefunc, tcn, timescaledb, tsm_system_rows, tsm_system_time, unaccent, uuid-ossp, vector, wrappers' supautils.extension_custom_scripts_path = '/etc/postgresql-custom/extension-custom-scripts' supautils.privileged_extensions_superuser = 'supabase_admin' supautils.privileged_role = 'supabase_privileged_role' diff --git a/nix/tests/prime-superuser.sql b/nix/tests/prime-superuser.sql index 3d3a2c8b7..e8382c004 100644 --- a/nix/tests/prime-superuser.sql +++ b/nix/tests/prime-superuser.sql @@ -11,10 +11,10 @@ -- ansible/files/postgresql_config: -- -- 1. "omitted because may be unsafe" — supautils.conf.j2. --- Covers the entries available in BOTH PG 15 and PG 17 builds. Two more --- entries from the same list, `adminpack` and `old_snapshot`, were --- removed from contrib in PG 17 and are loaded directly by --- nix/tests/sql/z_15_ext_interface.sql for the PG 15 path. +-- Covers the entries available in BOTH PG 15 and PG 17 builds. Three more +-- entries from the same list, `adminpack`, `amcheck`, and `old_snapshot`, were +-- removed from contrib in PG 17 or enabled for customers, and are loaded directly by +-- nix/tests/sql/z_15_ext_interface.sql for the PG 15 path (adminpack, old_snapshot only). -- -- 2. "omitted because deprecated" — supautils.conf.j2. -- Not in privileged_extensions, so non-superuser can't install. @@ -30,7 +30,6 @@ set client_min_messages = warning; -- Category 1: "may be unsafe" per supautils.conf.j2 -create extension if not exists amcheck; create extension if not exists file_fdw; create extension if not exists lo; create extension if not exists pageinspect; diff --git a/nix/tests/prime.sql b/nix/tests/prime.sql index 24fd8f2ea..9260e759a 100644 --- a/nix/tests/prime.sql +++ b/nix/tests/prime.sql @@ -9,12 +9,13 @@ set client_min_messages = warning; -- engines-with-smoke against hosted projects). They live in -- prime-superuser.sql instead — that covers: -- - the "may be unsafe" list from supautils.conf.j2 --- (amcheck, file_fdw, lo, pageinspect, pg_freespacemap, pg_surgery, pg_visibility) +-- (file_fdw, lo, pageinspect, pg_freespacemap, pg_surgery, pg_visibility) -- - the "deprecated" list from supautils.conf.j2 (intagg, xml2) -- Superuser-context harnesses (nix/checks.nix, docker-image-test, -- migrate-tool) source prime-superuser.sql in addition to this file. create extension if not exists address_standardizer; create extension if not exists address_standardizer_data_us; +create extension if not exists amcheck; create extension if not exists autoinc; create extension if not exists bloom; create extension if not exists btree_gin;