Claude Code's "don't ask again" saves passwords verbatim: 1,122 public files and a bug a bot closed in January
Claude Code already knows how to hide a secret. Its changelog lists redaction for shared transcripts and debug logs, masking of credentials in permission previews relayed to an approver, and scrubbing of ${VAR} values from MCP error messages. One place it still writes a password verbatim is the file that remembers which commands you approved.
That file is .claude/settings.local.json, and Apiiro researchers Shmulik Cohen and Matan Giladi have now counted how often it ends up public. Per their write-up, as reported by The Hacker News, they found 104,185 copies on public GitHub in 103,617 repositories. 1,122 of them, about 1.1%, hold at least one secret, 1,379 distinct values in total: 379 database passwords, 43 SSH logins for public servers, 42 GitHub, GitLab and npm tokens and 23 AWS keys among them. Counting git history, the committed .claude/settings.json and saved agent transcripts, Apiiro's total is 2,539 secrets in 1,994 repositories.
How a password gets there
When Claude Code asks to run a shell command and you pick "Yes, and don't ask again", it saves an allow rule. Anthropic's settings documentation says where: .claude/settings.local.json, inside the project. Sometimes the rule is a pattern like Bash(npm test *). Sometimes it is the exact command, and if that command was PGPASSWORD=... psql -h db.example.com, the password is now part of a JSON file in your repository folder.
None of this is new to Anthropic's tracker. Issue #5544, filed on August 11, 2025, is titled "approved bash commands containing credentials are stored as is with plain text credentials in settings.local.json". It got a duplicate-detection bot, two comments from the reporter, and on January 3 an automatic close as "not planned" after 60 days of inactivity. No one from Anthropic replied.
"Meant to stay local"
Boris Cherny of Anthropic's Claude Code team answered in the Hacker News thread on Saturday. His points: Claude Code has historically not done secret scrubbing, the team is "looking into what we can do", and .claude/settings.local.json "is meant to stay local... We automatically gitignore it when Claude creates the file, so in this case the files were manually created and checked in." He also argued that permission rules are "old hat" and that users should switch to auto mode, and later listed options the team will prototype: making auto mode catch this, "basic secret scanning", and others.
The documentation backs the first half of that. The first time Claude Code writes the file in a git repository, it adds **/.claude/settings.local.json to the user's global git excludes file, so git on that machine ignores it everywhere.
But that protection lives in one person's git config on one computer. It does not travel with the repository: a teammate's laptop, a CI runner or a container is covered only if Claude Code itself writes the file there first. And git ignores exclude rules for files it already tracks, so it cannot help a file that was committed once. Apiiro also reports that in 539 of the 1,105 repositories it traced, a commit listing Claude as co-author changed the file. That does not prove Claude Code created those files, but it does not fit neatly with "manually created and checked in" either.
Anthropic's own changelog has two entries that cut against the "it stays local" framing:
- 2.1.207 stopped auto mode reading
autoModefrom.claude/settings.local.json, describing the file in the changelog as "(repo-resident)". For security decisions, Anthropic already treats it as something that can arrive with a repository. - 2.1.307 fixed self-hosted runner sessions with
--use-anthropic-git-proxy"committing a.claude/settings.local.jsonleft in the clone by an earlier session". So at least one Claude Code path did commit this file on its own, until a recent release.
There is also a sibling bug. Issue #91270, filed September 1, reports that the VS Code extension wrote "always allow" grants into the committed .claude/settings.json instead of the local file. The reporter's team ended up writing a pre-commit hook to catch personal entries. A bot closed it as "not planned" on November 5, the same week Apiiro published.
Why the usual scanners miss it
Apiiro ran gitleaks and TruffleHog over all 1,122 secret-bearing files without their verification steps. Gitleaks flagged 564, TruffleHog 643, and 215 were caught by neither. Most of the misses are passwords typed inline, after PGPASSWORD=, sshpass -p or mysql -p, which look like ordinary words to a tool tuned for key formats. So another of Cherny's suggestions on HN, turning on your forge's secret scanning, helps with the AWS keys and tokens and much less with the database passwords, which are the largest group.
A few caveats on the numbers. Apiiro did not try any credential, so this is exposure, not confirmed compromise. One notified company did confirm its key had been live. Classification used format and context filters plus an LLM reviewer, and it hasn't been reproduced independently. Apiiro also sells the kind of scanning it recommends. As a rough sanity check on scale, GitHub's code search (which only indexes default branches) returned 90,112 files at .claude/settings.local.json paths containing the word "allow" when we queried it on November 8. That's the same order of magnitude as Apiiro's 104,185. We did not search the files' contents for secrets.
What changes now, and what doesn't
Claude Code 2.1.319, the newest version in the public changelog, has no entry about scrubbing secrets from saved rules. Until something ships, the fix is on the user's side, and the order matters:
- Rotate any password, token or key that has ever sat in an approved command. Deleting the file doesn't remove it from git history or from forks: Apiiro found 211 forks of 74 repositories carrying the same secrets.
git rm --cached .claude/settings.local.jsonand add it to the repository's own.gitignore, not just your global one.- Open the local file even if it was never committed, and delete rules that contain secrets. The file can also ride along in npm packages, Docker images and synced folders.
- Put secrets in environment variables (
$DB_URL) so the saved rule stores a name, not a value, and approve patterns rather than single commands.
Auto mode, Cherny's preferred answer, sidesteps the allow list for commands it judges safe. But as one HN commenter pointed out, when auto mode does ask about a sensitive command, the default answer still saves an allow rule to the same file; Cherny called that "a good catch". The "don't ask again" button is the cheapest place to fix this. Since 2.1.234, Claude Code masks credentials in permission previews it relays to a remote approver, so the code that recognizes a password in a command already exists. It just isn't applied to the rule it saves.
- Apiiro: coding agents leaking secrets on GitHub via "don't ask again" (Shmulik Cohen, Matan Giladi)
- The Hacker News: Claude Code's "Don't Ask Again" File Exposes Passwords and Keys in 1,122 Public Copies on GitHub
- Boris Cherny (Claude Code team) on Hacker News
- Claude Code docs: Settings files and precedence
- anthropics/claude-code #5544: approved bash commands containing credentials stored in plain text in settings.local.json
- anthropics/claude-code #91270: VS Code 'always allow' grants written to tracked .claude/settings.json
Comments
No comments yet. Be the first.