Affected area
Auth
Supabase CLI version
v2.109.1
Operating system
Windows 11
Installation method
Other
Command
Installation method: Scoop. not tied to command
Actual output
## Description
Supabase CLI 2.109.1 on Windows can resolve different Management API identities from different process contexts on the same computer and Windows user account.
The persistent Windows generic credential is:
- Target: `Supabase CLI:supabase`
- Username/account: `supabase`
- Type: `CRED_TYPE_GENERIC`
- Persistence: `CRED_PERSIST_LOCAL_MACHINE`
Repeated `supabase logout` commands exited successfully, but the credential remained. Its Windows `LastWritten` timestamp did not change, proving it was not deleted and recreated.
## Environment
- Windows 11
- Supabase CLI 2.109.1
- Installed through Scoop
- PowerShell 7.6.3
- Hosted Supabase projects under two different Supabase identities
- Commands run both interactively and through a desktop application's non-interactive process runner
## Observed behavior
Sanitized CLI traces identify two distinct authenticated Supabase users through the Management API response identity.
A representative sequence:
1. Interactive `supabase login` authenticates Identity B.
2. Interactive `supabase link` succeeds against Identity B's project.
3. Interactive `supabase projects list` returns Identity B's projects.
4. Minutes later, a non-interactive `supabase projects list` launched through another process context returns Identity A's projects.
5. No login, startup task, environment-variable change, or credential write occurs between steps 3 and 4.
This occurred repeatedly.
The behavior presents as if a deleted or replaced credential is being restored, but trace evidence instead shows different Windows process/security contexts resolving different authenticated identities.
## Logout behavior
Multiple `supabase logout` commands returned exit status 0, while the original Windows credential remained readable.
The CLI implementation treats keyring-unavailable/not-found as a successful not-logged-in outcome, so exit status 0 does not establish that the credential was deleted.
## Profile-file behavior
Deleting:
C:\Users\<user>\.supabase\profile
does not prevent credential loading. Debug output shows:
NotFound: FileSystem.readFile (...\.supabase\profile)
Using access token for profile: supabase
Using profile: supabase (supabase.co)
The CLI silently falls back to the built-in `supabase` profile and continues reading the Windows credential.
## Expected behavior
- The same Windows user and `CRED_PERSIST_LOCAL_MACHINE` target should resolve consistently across supported execution contexts.
- `supabase logout` should delete every current and legacy credential representation.
- Logout should not report success when the targeted credential remains.
- The CLI should expose which credential backend and exact target it is using.
- If the process cannot access or delete the expected credential context, it should return a clear nonzero error.
- A command must not silently target a different Supabase account or project because of process-launch context.
## Impact
This is more than a login inconvenience. A developer can believe they are operating against one Supabase account while migration, link, or database commands authenticate as another account.
That creates a risk of applying database changes to the wrong hosted project.
## Relevant implementation
Windows keyring lookup, legacy-target handling, and deletion:
https://github.com/supabase/cli/blob/v2.109.1/apps/cli/src/legacy/auth/legacy-credentials.layer.ts
Access-token lookup order:
https://github.com/supabase/cli/blob/v2.109.1/apps/cli-go/internal/utils/access_token.go
Logout behavior:
https://github.com/supabase/cli/blob/v2.109.1/apps/cli/src/legacy/commands/logout/logout.handler.ts
I can provide a sanitized timeline of command traces and Windows credential metadata. Raw trace files cannot be attached because CLI 2.109.1 also records unredacted project secret keys in those files; that security issue is being reported separately.
Expected behavior
The same Windows user and CRED_PERSIST_LOCAL_MACHINE target should resolve consistently across supported execution contexts.
Steps to reproduce
-
On Windows 11 with Supabase CLI 2.109.1, create an isolated Supabase home with no telemetry configuration:
$env:SUPABASE_HOME = Join-Path $env:TEMP ("supabase-cli-trace-repro-" + [guid]::NewGuid())
Do not run supabase telemetry enable.
Create a minimal CLI project:
New-Item -ItemType Directory supabase-trace-repro
Set-Location supabase-trace-repro
supabase init
Authenticate normally:
supabase login
Link a throwaway hosted project that uses the current sb_publishable_ / sb_secret_ API-key format:
supabase link --project-ref
No secret key needs to be supplied manually. The CLI obtains the project keys while linking and uses the secret key for its REST, Auth, and Storage health requests.
Locate the newest automatically created trace:
$tracePath = (
Get-ChildItem "$env:SUPABASE_HOME\traces*.ndjson" |
Sort-Object LastWriteTime |
Select-Object -Last 1
).FullName
Run this redacting check. It reports whether an unredacted secret exists without printing the key:
Get-Content $tracePath | ForEach-Object {
try {
$event = $_ | ConvertFrom-Json -ErrorAction Stop
} catch {
return
}
$apiKey = [string]$event.attributes.'http.request.header.apikey'
if ($apiKey) {
[pscustomobject]@{
Path = [string]$event.attributes.'url.path'
IsUnredactedSecretKey = $apiKey.StartsWith('sb_secret_')
IsRedacted = $apiKey -eq ''
}
}
}
Observe entries for endpoints such as /rest/v1/, /auth/v1/health, and /storage/v1/version where:
IsUnredactedSecretKey : True
IsRedacted : False
Expected result: credentials are never written to trace files, or the apikey value is recorded only as .
Actual result: the complete sb_secret_ value is stored in the NDJSON trace despite telemetry never being explicitly enabled.
Crash report ID
No response
Docker and service versions
Additional context
No response
Affected area
Auth
Supabase CLI version
v2.109.1
Operating system
Windows 11
Installation method
Other
Command
Installation method: Scoop. not tied to commandActual output
Expected behavior
The same Windows user and
CRED_PERSIST_LOCAL_MACHINEtarget should resolve consistently across supported execution contexts.Steps to reproduce
On Windows 11 with Supabase CLI 2.109.1, create an isolated Supabase home with no telemetry configuration:
Create a minimal CLI project:
New-Item -ItemType Directory supabase-trace-repro
Set-Location supabase-trace-repro
supabase init
Authenticate normally:
supabase login
Link a throwaway hosted project that uses the current sb_publishable_ / sb_secret_ API-key format:
supabase link --project-ref
No secret key needs to be supplied manually. The CLI obtains the project keys while linking and uses the secret key for its REST, Auth, and Storage health requests.
Locate the newest automatically created trace:
$tracePath = (
Get-ChildItem "$env:SUPABASE_HOME\traces*.ndjson" |
Sort-Object LastWriteTime |
Select-Object -Last 1
).FullName
Run this redacting check. It reports whether an unredacted secret exists without printing the key:
Get-Content $tracePath | ForEach-Object {
try {
$event = $_ | ConvertFrom-Json -ErrorAction Stop
} catch {
return
}
$apiKey = [string]$event.attributes.'http.request.header.apikey'
if ($apiKey) {
[pscustomobject]@{
Path = [string]$event.attributes.'url.path'
IsUnredactedSecretKey = $apiKey.StartsWith('sb_secret_')
IsRedacted = $apiKey -eq ''
}
}
}
Observe entries for endpoints such as /rest/v1/, /auth/v1/health, and /storage/v1/version where:
IsUnredactedSecretKey : True
IsRedacted : False
Expected result: credentials are never written to trace files, or the apikey value is recorded only as .
Actual result: the complete sb_secret_ value is stored in the NDJSON trace despite telemetry never being explicitly enabled.
Crash report ID
No response
Docker and service versions
Additional context
No response