Version
@nuxtjs/supabase 2.0.9 (current main)
Summary
#598 / PR #599 removed headers from the final-failure log in src/runtime/utils/fetch-retry.ts, but the rest of init is still logged — and that includes init.body:
if (attempt === retries) {
const { headers: _headers, ...safeInit } = init ?? {}
console.error(`Error fetching request ${req}`, error, safeInit)
throw error
}
For requests supabase-js sends to /auth/v1/token, init.body contains credentials:
?grant_type=refresh_token → {"refresh_token":"..."}
?grant_type=password → the user's email and password
So the body has the same failure mode #598 fixed for headers: any auth request that fails all 3 retries (network blip, device offline, rate limit) logs the credential via console.error, and any runtime that captures console output persists it — Sentry's default console breadcrumbs attach it to captured events, and the same applies to Cloudflare Workers Observability, Vercel log drains, and stdout shipping.
A leaked refresh token is a live session: it can be exchanged for a fresh access + refresh token pair by anyone with read access to the logging destination.
Reproduction
Any request with a sensitive body that fails 3 times, e.g. go offline (or block *.supabase.co) with a session due for refresh; the final attempt logs {"method":"POST","body":"{\"refresh_token\":\"...\"}"}.
Proposed fix
Extend the #599 destructure by one key:
const { headers: _headers, body: _body, ...safeInit } = init ?? {}
The body is never useful for diagnosing a fetch failure (the error carries the cause), so there's nothing to redact selectively.
Happy to open a PR.
Version
@nuxtjs/supabase2.0.9 (currentmain)Summary
#598 / PR #599 removed
headersfrom the final-failure log insrc/runtime/utils/fetch-retry.ts, but the rest ofinitis still logged — and that includesinit.body:For requests supabase-js sends to
/auth/v1/token,init.bodycontains credentials:?grant_type=refresh_token→{"refresh_token":"..."}?grant_type=password→ the user's email and passwordSo the body has the same failure mode #598 fixed for headers: any auth request that fails all 3 retries (network blip, device offline, rate limit) logs the credential via
console.error, and any runtime that captures console output persists it — Sentry's default console breadcrumbs attach it to captured events, and the same applies to Cloudflare Workers Observability, Vercel log drains, and stdout shipping.A leaked refresh token is a live session: it can be exchanged for a fresh access + refresh token pair by anyone with read access to the logging destination.
Reproduction
Any request with a sensitive body that fails 3 times, e.g. go offline (or block
*.supabase.co) with a session due for refresh; the final attempt logs{"method":"POST","body":"{\"refresh_token\":\"...\"}"}.Proposed fix
Extend the #599 destructure by one key:
The body is never useful for diagnosing a fetch failure (the error carries the cause), so there's nothing to redact selectively.
Happy to open a PR.