Repository navigation
Sandbox can read Zero's own OAuth and provider credential stores #675
Description
Activity
- addedissue-approvedReviewed and approved by the core team; community PRs may implement this issue.Reviewed and approved by the core team; community PRs may implement this issue.
on Jul 21, 2026 - added a commit that references this issue
on Jul 27, 2026 Fixed by #801, merged today. Verified against current
mainrather than inferred from the diff, drivingcredentialDenyReadPathsForEnvironmentwith the whole store materialised, since the builder filters to paths that exist:denied=true ~/.config/zero/oauth-tokens.json denied=true ~/.config/zero/credentials.json denied=true ~/.config/zero/credentials.enc denied=true ~/.config/zero/credentials.enc.secret denied=true ~/.config/zero/config.jsonThat is every file this issue named.
The fix denies the directory rather than the individual files, which matters for the reason this issue exists. An earlier revision denied
config.jsonalone, which is the one file in there that deliberately holds no secrets, whilecredentials.encand its adjacent.secretkey stayed readable together. Denying the directory also covers nested paths and files nobody enumerated,mcp-oauth-tokens.jsonamong them.Two things this does NOT cover, both raised on the PR and both still open, so they should not be read as closed here:
~/.ssh,~/.gnupg,~/.git-credentialsand~/.config/git/credentialsare all still readable by a sandboxed command. Worth its own issue if someone wants that boundary closed too.Also unchanged on Windows, where the deny list is skipped by design. #808 approaches that side differently, by giving the sandbox its own identity so the credential store is unreachable by construction rather than by enumeration.
Split out of here as #815, with the probe output and the git-config wrinkle written up. Flagging it on the PR thread too since @gnanam1990 raised these as the non-blocking remainder.
- added a commit that references this issue
on Aug 1, 2026 - added 2 commits that reference this issue
on Aug 21, 2026
Summary
Sandboxed commands use a read-all/write-restricted filesystem posture, but the default credential deny list only covers
~/.aws,~/.config/gcloud,~/.azure, and theGOOGLE_APPLICATION_CREDENTIALStarget. Zero's own credential-bearing files remain readable.This exposes:
~/.config/zero/oauth-tokens.jsoncredentials.jsonwhen plaintext provider-key storage is selectedcredentials.encand its adjacent.secretAES keyconfig.json, which can contain inlineapiKey,authHeaderValue, and secretcustomHeadersRelevant code
internal/sandbox/profile.go:permissionProfileReadRootsstarts with the filesystem root;credentialDenyReadPathsdoes not include Zero files.internal/oauth/store.go: the default storage case is the plaintext file backend.internal/credstore/credstore.go: encrypted storage usescredentials.encwithsecurefile.NewCrypter(path + ".secret").internal/config/types.go: provider profiles can persist inline keys and credential-bearing headers.Observed at commit
6fc1220.Impact
Environment scrubbing does not protect credentials stored on disk. Reading both the encrypted provider store and its co-located key is equivalent to reading plaintext.
Suggested fix
config.json, OAuth/MCP token stores,credentials.json,credentials.enc, and its.secret.