diff --git a/lints/0011_function_search_path_mutable.sql b/lints/0011_function_search_path_mutable.sql index 36ed1db..a13fbfe 100644 --- a/lints/0011_function_search_path_mutable.sql +++ b/lints/0011_function_search_path_mutable.sql @@ -37,6 +37,10 @@ where '_timescaledb_cache', '_timescaledb_catalog', '_timescaledb_config', '_timescaledb_internal', 'auth', 'cron', 'extensions', 'graphql', 'graphql_public', 'information_schema', 'net', 'pgmq', 'pgroonga', 'pgsodium', 'pgsodium_masks', 'pgtle', 'pgbouncer', 'pg_catalog', 'realtime', 'repack', 'storage', 'supabase_functions', 'supabase_migrations', 'tiger', 'topology', 'vault' ) and dep.objid is null -- exclude functions owned by extensions + -- Exclude aggregates: their pg_proc entry is a placeholder with no body and + -- CREATE AGGREGATE has no SET clause, so they can never carry a search_path. + -- The support functions they are built from are linted in their own right. + and p.prokind <> 'a' -- Search path not set and not exists ( select 1 diff --git a/splinter.sql b/splinter.sql index 9cd66c9..a69a3e0 100644 --- a/splinter.sql +++ b/splinter.sql @@ -696,6 +696,10 @@ where '_timescaledb_cache', '_timescaledb_catalog', '_timescaledb_config', '_timescaledb_internal', 'auth', 'cron', 'extensions', 'graphql', 'graphql_public', 'information_schema', 'net', 'pgmq', 'pgroonga', 'pgsodium', 'pgsodium_masks', 'pgtle', 'pgbouncer', 'pg_catalog', 'realtime', 'repack', 'storage', 'supabase_functions', 'supabase_migrations', 'tiger', 'topology', 'vault' ) and dep.objid is null -- exclude functions owned by extensions + -- Exclude aggregates: their pg_proc entry is a placeholder with no body and + -- CREATE AGGREGATE has no SET clause, so they can never carry a search_path. + -- The support functions they are built from are linted in their own right. + and p.prokind <> 'a' -- Search path not set and not exists ( select 1 diff --git a/test/expected/0011_function_search_path_mutable.out b/test/expected/0011_function_search_path_mutable.out index b24c556..4b30c8b 100644 --- a/test/expected/0011_function_search_path_mutable.out +++ b/test/expected/0011_function_search_path_mutable.out @@ -47,4 +47,41 @@ begin; ------+-------+-------+--------+------------+-------------+--------+-------------+----------+----------- (0 rows) + -- An aggregate is not reported: CREATE AGGREGATE has no SET clause, so its + -- pg_proc entry can never carry a search_path + create function public.uuid_min(uuid, uuid) + returns uuid + set search_path = '' + language sql + immutable strict + as $$ + select least($1, $2); + $$; + create aggregate public.min_uuid(uuid) ( + sfunc = public.uuid_min, + stype = uuid, + combinefunc = public.uuid_min, + parallel = safe + ); + -- 0 issues + select * from lint."0011_function_search_path_mutable"; + name | title | level | facing | categories | description | detail | remediation | metadata | cache_key +------+-------+-------+--------+------------+-------------+--------+-------------+----------+----------- +(0 rows) + + -- The support function is still linted on its own + create or replace function public.uuid_min(uuid, uuid) + returns uuid + language sql + immutable strict + as $$ + select least($1, $2); + $$; + -- 1 issue, for public.uuid_min and not for the aggregate + select * from lint."0011_function_search_path_mutable"; + name | title | level | facing | categories | description | detail | remediation | metadata | cache_key +------------------------------+------------------------------+-------+----------+------------+---------------------------------------------------------------+-------------------------------------------------------------+--------------------------------------------------------------------------------------------------+--------------------------------------------------------------+------------------------------------------------------------------------------- + function_search_path_mutable | Function Search Path Mutable | WARN | EXTERNAL | {SECURITY} | Detects functions where the search_path parameter is not set. | Function \`public.uuid_min\` has a role mutable search_path | https://supabase.com/docs/guides/database/database-linter?lint=0011_function_search_path_mutable | {"name": "uuid_min", "type": "function", "schema": "public"} | function_search_path_mutable_public_uuid_min_f4e24529160b926c46151c3f612a6c29 +(1 row) + rollback; diff --git a/test/sql/0011_function_search_path_mutable.sql b/test/sql/0011_function_search_path_mutable.sql index a727fce..182100c 100644 --- a/test/sql/0011_function_search_path_mutable.sql +++ b/test/sql/0011_function_search_path_mutable.sql @@ -39,5 +39,38 @@ begin; select * from lint."0011_function_search_path_mutable"; + -- An aggregate is not reported: CREATE AGGREGATE has no SET clause, so its + -- pg_proc entry can never carry a search_path + create function public.uuid_min(uuid, uuid) + returns uuid + set search_path = '' + language sql + immutable strict + as $$ + select least($1, $2); + $$; + + create aggregate public.min_uuid(uuid) ( + sfunc = public.uuid_min, + stype = uuid, + combinefunc = public.uuid_min, + parallel = safe + ); + + -- 0 issues + select * from lint."0011_function_search_path_mutable"; + + -- The support function is still linted on its own + create or replace function public.uuid_min(uuid, uuid) + returns uuid + language sql + immutable strict + as $$ + select least($1, $2); + $$; + + -- 1 issue, for public.uuid_min and not for the aggregate + select * from lint."0011_function_search_path_mutable"; + rollback;