Segfault instead of 42501: calling a function without EXECUTE privilege after SET ROLE crashes the cluster (17.6.1.106, aarch64)
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 48/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- postgresql
- Domain
- databases
Research direction
Start by running the four-line SQL reproduction against the reported PostgreSQL 17.6 image, then compare its behavior with a stock PostgreSQL 17.6 image as suggested. Trace the privilege check for a function call after SET ROLE and add a regression test covering the denied EXECUTE case. Done means the server returns 42501 without terminating the backend or cluster.
Written by the indexing model from the issue text.
Description
Summary
On supabase/postgres:17.6.1.106, calling a function that the current role lacks EXECUTE privilege on, after SET ROLE, segfaults the backend instead of raising 42501 permission denied. The postmaster then terminates every other connection and the cluster enters crash recovery.
Because the whole cluster restarts, this is not a contained error: every in-flight connection dies, PostgREST loses its listener and re-initialises its pool, and unrelated requests fail with PGRST002 for the duration.
Reproduction
Four lines. No extension, no fixture, no SECURITY DEFINER, no SET clause on the function:
CREATE FUNCTION public.probe() RETURNS text LANGUAGE sql STABLE
AS $$ SELECT 'ok'::text $$;
REVOKE EXECUTE ON FUNCTION public.probe() FROM PUBLIC, anon, authenticated;
SET ROLE authenticated;
SELECT public.probe();
Expected: ERROR: 42501: permission denied for function probe
Actual: the connection dies and the cluster recovers.
psql: server closed the connection unexpectedly
Server log:
LOG: server process (PID …) was terminated by signal 11: Segmentation fault
DETAIL: Failed process was running: SET ROLE authenticated; SELECT public.probe();
LOG: terminating any other active server processes
LOG: database system was not properly shut down; automatic recovery in progress
Environment
| image | public.ecr.aws/supabase/postgres:17.6.1.106 |
| PostgreSQL | 17.6 (aarch64-unknown-linux-gnu, gcc 15.2.0) |
| host | Docker Desktop on macOS, Apple Silicon |
| Supabase CLI | 2.98.2 |
What we ruled out
We hit this ~36 times across a working day and initially misdiagnosed it several ways. Each of these was excluded by measurement, in case it saves someone the same path:
- Connection-pool exhaustion — sampled
pg_stat_activityevery 3 s across a full workload: peak 8 of PostgREST's 10, mostly 3, always returning to 1. Never at the limit. - A resource limit —
shared_buffers128 MB,work_mem4 MB, container using 312 MiB of 15.6 GiB with no hard limit. - JIT —
jit_above_costis 100000; representative plan costs here are ~24, so JIT never engages. - A specific extension (
pgmq) — our first crashes all ran throughpgmq.send(), but barepgmq.send(...)as a privileged role is fine. The queue is incidental; the ACL is not. SECURITY DEFINER— crashes with and without it.- A
SET search_pathclause on the function — crashes with and without it.
The single discriminator is the privilege. Adding GRANT EXECUTE ON FUNCTION public.probe() TO authenticated; makes every variant run cleanly; revoking it crashes reliably.
Impact
Any test or application path that asserts an unprivileged caller is refused will take the database down rather than receive the refusal. In our case two RLS regression tests exist specifically to prove that an unprivileged role cannot call two functions — so asserting a refusal is itself the crash, and the failures land on whichever unrelated suite happened to be running.
Happy to run further narrowing (e.g. against a stock PostgreSQL 17.6 image to confirm whether this is upstream or image-specific) if that would help.
- Dominant language
- Nix
- Stars
- 1.8k
- Forks
- 266
- Avg merge
- 2d 8h
- Merged PRs (30d)
- 25
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from supabase/postgres
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
-
`supabase/postgres:17.6.1.105` (amd64) — backend SIGSEGV during a heavy pgTAP file, CI-CPU-specific Open
Difficulty 5/5 Over a week Newbie friendliness 30/100
All issues in supabase/postgres
Similar issues
-
bug: AI Gateway client filter lists "Unknown" twice when NULL and literal Unknown clients coexist Openbug
Difficulty 2/5 1-3 hours Newbie friendliness 90/100
-
[BUG] A column whose default is the empty string is drawn in the ER diagram as having no default Openbug database-provider good first issue hacktoberfest
Difficulty 2/5 1-3 hours Newbie friendliness 90/100
libredb/libredb-studio#1030 · 6 comments ·
-
comp-datalake
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
ClickHouse/ClickHouse#121222 ·
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
-
bug redshift
Difficulty 2/5 1-3 hours Newbie friendliness 88/100