sandbox credentials.files mask produces no file at all for ~/.config/gh/hosts.yml
Sandbox credentials.files mask produces no file at all for ~/.config/gh/hosts.yml
Environment
- Claude Code version:
2.1.270 - Install method: native
- Platform: Linux (remote/EC2-hosted session, launched via the Claude Code desktop app's remote client)
ghversion:2.100.0
Config (~/.claude/settings.json, relevant excerpt)
{
"sandbox": {
"enabled": true,
"network": {
"allowedDomains": ["github.com", "api.github.com", "..."],
"strictAllowlist": true,
"tlsTerminate": {}
},
"filesystem": {
"denyRead": ["~/"],
"allowRead": ["~/repos", "~/.gitconfig", "~/.config/git", "~/.config/gh/config.yml", "~/.cache/aws-bedrock", "~/.claude/plugins"]
},
"credentials": {
"files": [
{
"path": "~/.config/gh/hosts.yml",
"mode": "mask",
"extract": "oauth_token:\\s*(\\S+)",
"injectHosts": ["api.github.com"],
"maskDuplicates": true,
"onExtractNoMatch": "error"
}
]
}
}
}
Expected behavior
Per docs (/docs/en/sandboxing#mask-credential-files): on Linux/WSL2, a sandboxed command reading ~/.config/gh/hosts.yml should see a sentinel copy (real token replaced with a placeholder), and outbound requests to api.github.com should get the real token substituted by the sandbox proxy.
Actual behavior
The file does not exist at all inside the sandbox — not a sentinel, not the real file, nothing:
$ cat ~/.config/gh/hosts.yml
cat: /home/ubuntu/.config/gh/hosts.yml: No such file or directory
$ ls -la ~/.config/gh/
total 4
drwxr-xr-x 2 ubuntu ubuntu 60 ... .
drwx------ 4 ubuntu ubuntu 80 ... ..
-rw------- 1 ubuntu ubuntu 1660 ... config.yml
hosts.yml doesn't appear in the directory listing at all — not even as a masked entry. As a consequence, gh auth status reports "not logged in" and git ls-remote/git push/git pull over HTTPS fail with could not read Username for 'https://github.com' inside the sandbox, even though the same commands work fine outside it.
Verification already done (all pass)
extractregex matches: confirmed viagrep -qE 'oauth_token:[[:space:]]*\S+' ~/.config/gh/hosts.ymloutside the sandbox → matches (twice —hosts.ymlhasoauth_token:both nested underusers.<login>and duplicated at the top level, which is normal for currentghversions).- File validity:
file ~/.config/gh/hosts.yml→ASCII text;wc -c→ 216 bytes. Well under the documented 8 MiB cap, not a directory, not a glob. network.tlsTerminate: {}is set, and confirmed active empirically —HTTPS_PROXY/HTTP_PROXY/GIT_SSH_COMMANDinside the sandbox are all wired through the sandbox's TLS-terminating proxy (localhost:3128).api.github.comis present in bothinjectHostsandnetwork.allowedDomains.- Config schema matches the documented example in
/docs/en/sandboxing#mask-credential-filesexactly, plus two optional fields (maskDuplicates,onExtractNoMatch) valid since v2.1.224 (we're on 2.1.270). - Settings symlink is live and correct:
~/.claude/settings.json→<project>/dotfiles/claude_1/.claude/settings.json, confirmed viareadlink -f. - Not a stale-session issue: reproduced in a session started fresh after the config was last edited.
/sandbox→ Config tab shows the base filesystem/network restrictions (~/.config/ghcorrectly shown denied except the explicitconfig.ymlallowRead exception) but has no dedicated section reportingsandbox.credentialsmask status, so it can't confirm/deny whether the mask ran. No warning banner appeared at session start. No Dependencies tab appeared (so the optional Linux seccomp package isn't the issue).
None of the documented fallback-to-deny conditions (directory path, glob pattern, file >8 MiB, non-UTF-8) apply, and onExtractNoMatch: "error" shouldn't trigger since the regex does match. Per docs, masking is supposed to be enforced independently of the filesystem layer's denyRead, so the broad "denyRead": ["~/"] shouldn't prevent the mask's sentinel from appearing — but empirically, it looks like it does (or something else silently drops this entry) for this file.
Suspected cause (unconfirmed)
Possibly specific to this environment: a remote/EC2-hosted session launched via the desktop app's remote client, rather than a local interactive claude CLI session. This box has at least one other documented instance of remote/EC2-launched sessions not getting credential-handling behavior that's otherwise expected (AWS credential env-var injection via awsCredentialExport doesn't reach the sandboxed process env in this same launch mode, per separate investigation). If file-mode credentials.files masking has a similar gap for this launch path, that would explain a silent, total absence rather than a reported misconfiguration.
Workaround in use
Route gh/git operations over HTTPS through the unsandboxed-command escalation path instead of relying on the mask.