Sandbox proxy credentials are sent to Git credential helpers on macOS (`fatal: failed to store: 100001`)
Environment
Claude Code 2.1.280, macOS, sandbox enabled. Reproduced with Homebrew Git 2.55.0; Apple Git 2.54.0 showed the same behavior.
What happens
A sandboxed git ls-remote origin HEAD against a public HTTPS GitHub repository prints fatal: failed to store: 100001, although the command itself succeeds. With GIT_TRACE=1, the only credential-helper call is git credential-osxkeychain store, and the macOS unified log shows that helper's SecItemAdd call failing with Operation not permitted.
Cause
Claude Code gives sandboxed commands an authenticated local HTTP proxy through HTTPS_PROXY (http://<user>:<pass>@localhost:<port>). Git parses that proxy URL into a separate proxy_auth credential, and after a successful request handle_curl_result() in http.c calls credential_approve() on it, which sends store to every configured helper.
Both Homebrew Git's system configuration (/opt/homebrew/etc/gitconfig) and Apple Git's Command Line Tools configuration set credential.helper = osxkeychain for every URL. The write attempt therefore concerns the local proxy credential, even though the remote repository is public. If Keychain writes were permitted inside the sandbox, for example through the grant requested in #87008, the helper would store that proxy credential in the login keychain.
This is a more specific cause than the GitHub credential write-back described in #87008.
Reproduction
- On macOS, enable the Claude Code sandbox and keep Git's default system
osxkeychaincredential helper. - In a repository with a public HTTPS GitHub
origin, have Claude runGIT_TRACE=1 git ls-remote origin HEADas a sandboxed command, one thatsandbox.excludedCommandsdoes not exempt. - The trace shows
git credential-osxkeychain store, and the output ends withfatal: failed to store: 100001.
Suggested fix
Keep the sandbox proxy's http://localhost:<port> credential away from Git credential helpers while preserving helpers for remote hosts. Claude Code already injects http.proxyAuthMethod=basic through GIT_CONFIG_PARAMETERS; adding a URL-scoped empty credential.http://localhost:<port>.helper= there is one way to do it.
In a test with logging stub helpers, adding -c 'credential.http://localhost:54321.helper=' stopped store for that proxy context, while a GitHub-scoped helper still received its credential and another host still used the system helper. The port has to come from the current sandbox proxy: nine concurrent Claude Code processes on the reporting machine listened on nine different localhost ports, and Git's URL matching requires an exact port.
A user-side workaround is an empty global credential.helper placed before any per-host [credential "<url>"] sections. It removes the system-wide helper for every host without its own helper, so it is broader than the proxy-scoped fix.