Hello Supabase Support,
We are preparing a restricted application runtime login for our staging project and need clarification on the supported credential-provisioning procedure.
Our security requirement is to prevent both plaintext database passwords and their authentication verifiers, such as SCRAM verifiers, from being recorded in relevant hosted logs while retaining appropriate security and audit logging.
Could you please clarify:
What supported procedure do you recommend for creating and rotating a custom PostgreSQL LOGIN role on our hosted PostgreSQL version?
Does that procedure prevent plaintext passwords and authentication verifiers from being recorded in PostgreSQL statement logs, error logs, pgAudit, Supavisor diagnostics, and relevant Supabase-managed platform or internal logs?
Where applicable, is protection applied before log storage, or does it only redact information displayed in the dashboard?
Are there logging channels or diagnostic workflows for which this protection cannot be guaranteed?
If temporary database access is the recommended alternative, what equivalent protections apply to the access token and associated authentication material?
Can you provide the relevant documentation or a written security statement applicable to our project configuration?
We do not intend to share actual credentials, passwords, tokens, or authentication verifiers in this support request.
Our goal is to use a least-privilege staging runtime identity, keep migration privileges separate, and preserve TLS verification.
Thank you.
The user seeks guidance on securely provisioning PostgreSQL credentials without exposing plaintext passwords or verifiers in logs. They request clarification on supported procedures for creating and rotating custom LOGIN roles, and how logging channels handle sensitive information. They also inquire about temporary database access as an alternative.
Following this from the adjacent thread (#51499) since it's the same credential-lifecycle family — your questions here go deeper into the logging side, and the distinctions you're drawing (pre-storage vs. dashboard redaction) are the right ones to insist on for a compliance posture. Here's the mechanics as accurately as I can state them:
1. Supported procedure for creating/rotating a custom LOGIN role
The platform-supported path is plain SQL as postgres (which holds CREATEROLE on hosted): CREATE ROLE app_runtime LOGIN PASSWORD '...' issued from the SQL editor or via supabase db ... from the CLI. For rotation with no shared state, the brief-dual-role pattern from #51499 applies (create app_runtime_v2, redeploy with the new connection string, drop the old role after drain). For a written security statement applicable to your project configuration (your Q6), that genuinely needs a support ticket — what the community can give you is mechanics; the attestation is a commercial/support artifact.
2. Where the password/verifier can and cannot appear, per channel
pg_stat_statements: safe by construction, and the protection is pre-storage. Query text is normalized at capture time — literals become $n before anything is stored. An ALTER ROLE ... PASSWORD 'SCRAM-SHA-256$...' is stored as ALTER ROLE ... PASSWORD $1. This is the strongest guarantee in the stack: normalization happens before storage, not redaction after.ALTER ROLE with an embedded verifier will appear if ROLE/DDL classes are on. Protection here is procedural: rotate via a role/session that pgAudit doesn't audit (pgAudit can be scoped by role), or accept that the verifier appears in your own audit trail (it's a hash, not the password — but your stated requirement excludes verifiers too, so scope pgAudit accordingly).3. Pre-storage vs. redaction — the honest map
| Channel | Protection type |
|---|---|
| pg_stat_statements | Normalization at capture (pre-storage) — safe |
| Postgres error logs | None for the failing statement text — rotate carefully |
| pgAudit (if DDL on) | None — procedural scoping required |
| Dashboard telemetry | Assume retained; display redaction is post-storage |
| Migration files in git | None — the classic leak vector; never commit rotation |
4. The guaranteed-clean path
If your requirement is "no plaintext and no verifier in any hosted log," the supported procedure that achieves it: rotate from a psql session using \password (the verifier is computed client-side and the wire statement is the ALTER ROLE — same as any client, but your local shell history and any local logging are under your control), or use the CLI's connection flow. Then keep rotation out of migration files, dashboards, and audited sessions.
5. Temporary database access (your Q5)
The temporary-access flow issues short-lived credentials through the platform; the token itself and the exchange material are managed by Supabase's auth plane rather than appearing as role passwords in Postgres logs. The equivalent protections: short TTL (expiry is the rotation), no SCRAM verifier in the Postgres catalog to leak, and the auth exchange happening outside statement-logging surfaces. For staging workloads where a standing LOGIN role isn't strictly required, temporary access is arguably the better answer to your requirement — it removes the persistent-credential lifecycle your whole question set is about.
One caveat on all of the above: channel behavior is configuration-dependent (pgAudit classes, log retention settings, plan tier). For an auditable statement of your project's actual configuration, the support ticket in Q6 is the right instrument — worth requesting with your specific pgAudit/retention settings attached so the statement is precise rather than generic.
Thank you for the detailed explanation. Your response is helpful, particularly in distinguishing PostgreSQL statement logging, pg_stat_statements, pgAudit, Supavisor diagnostics, and temporary database access.
I have reviewed your recommendations against the PostgreSQL 17 documentation and implementation, as well as the constraints of our Supabase-hosted staging environment. Before adopting either approach, I need to clarify a few security-critical points.
Our requirement is that neither the plaintext database password nor its SCRAM authentication verifier should be recorded in the relevant retained logs or diagnostic stores. We also need to preserve our existing security-audit logging rather than disable it simply to provision credentials.
Could you please clarify the following?
1. Provisioning a dedicated PostgreSQL LOGIN role
You recommended using psql \password as the cleanest method. I understand that it encrypts the password client-side before sending the password-change command, thereby protecting the plaintext password from exposure through command history and the server-side statement.
However, the server receives an ALTER ROLE command containing the verifier. Our staging configuration reportedly retains log_statement=ddl.
pg_stat_statements reliably normalize the verifier in this particular utility statement on PostgreSQL 17.11, or is that an assumption based on general query-normalization behaviour?Please distinguish protection of the plaintext password from protection of the verifier. I am not looking to disable necessary auditing or rely on a statement simply succeeding rather than failing.
2. Supabase temporary database access
You also suggested token-based temporary access as an alternative to a persistent database password.
Could you clarify:
I understand that temporary access can avoid setting a persistent database password through role DDL. However, that alone does not establish that the token is protected from every relevant logging channel or that the application can use it reliably.
3. Practical, supported recommendation
For our hosted PostgreSQL 17.11 staging project, with log_statement=ddl and security auditing preserved, which supported method would you recommend to provision and rotate a restricted application LOGIN role while preventing both plaintext passwords and SCRAM verifiers from entering relevant retained logs and diagnostics?
Please identify the applicable redaction mechanism, the version to which it applies, and whether protection occurs before the data is stored. If any logging channel is not covered or cannot be verified, please state that limitation explicitly.
I appreciate your help. I am trying to establish a defensible, supportable approach before provisioning credentials or enabling customer authentication in staging.