Claude Code's Don't Ask Again Button Wrote Database Passwords Into 1,122 Public Repos
Choosing "don't ask again" in Claude Code stores the approved command, database password and all, as plain text in a project file. Apiiro found 1,122 of those files on public GitHub carrying 1,379 real secrets, and two popular scanners missed 215 of them.
- "Don't ask again" in Claude Code saves the whole command, password included, in plain text.
- Apiiro found 1,122 of those files on public GitHub holding 1,379 real secrets.
- In nearly half the repos with live secrets, Claude co-authored the commit.
Database passwords and API keys that Claude Code users approved with a single click are sitting in 1,994 public GitHub repositories. The security firm Apiiro published the research on November 5, counting 2,539 real secrets exposed this way. Among them: the database owner password for a medical records app, and a root SSH password for an internet-facing server.
If you use Claude Code, this is a button you press several times a day. Few people knew what it writes down, or where.
One Button Writes Your Password Into a File
Claude Code asks for permission before it runs a terminal command. The options are "yes", "yes, and don't ask again", and "no". Pick the second one and the same command runs unprompted from then on. Per the permissions docs, that approval is stored permanently per repository, in .claude/settings.local.json at the repository root.
The problem is what gets stored. Claude Code writes the approved command string itself as the allow rule. Ask it why the staging server login is failing and Claude reads the connection details out of your config, then proposes something like PGPASSWORD=yourpassword psql -h host ..., because without the password the command does nothing. Click "don't ask again" there and a line containing that password lands in a JSON file as plain text.

Anthropic knows this file should not leave the machine. The settings docs say that when Claude Code first creates it, it adds **/.claude/settings.local.json to the user's global git exclude file. Commits made on that machine skip the file.
Apiiro's point is that the protection is attached to the machine, not the repository, which leaves four gaps:
- A folder that becomes a git repository after the file already exists is not covered.
- Clone the repo on another machine and that machine's exclude list has no such rule.
- A file that is already committed stays tracked no matter what you add to an exclude list.
- Nothing is added to the repository's own
.gitignore, so no protection travels with the project.
Apiiro attributes this to Claude Code the program, not the model, and reproduced it on the current Opus 5.5 and Fable 5.1. Comparing the documentation of 16 coding agents, Claude Code was the only one confirmed to write full approved commands into a project file by default.
1,379 Secrets on Public GitHub
Between November 1 and 3, Apiiro downloaded every copy of this file it could find through GitHub code search. It collected 104,185 files across 103,617 repositories, and 1,122 of them (1.1%) contained real secrets, 1,379 unique ones.

More than one in three was a key that opens a database directly. Database passwords accounted for 379 and Supabase service-role keys for 122. AI model API keys came to 149. Apiiro identified 63 affected organizations, including:
- A database vendor's own admin-privileged cloud key, with no expiry.
- The cloud Postgres owner password belonging to the IT services firm that built a medical records app.
- A payments startup's Postgres password, and a software agency's production Square token.
- An OpenAI-format API key in an open source project with more than 1,000 stars.
- A university repository that had permanently approved a root SSH command against a public server.
Apiiro notified each organization on November 2 and 3, and one confirmed the key was still live. The report states that researchers never actually used the credentials, so whether the rest still work is unknown.
Apiiro also traced who committed the files. Of 1,105 repositories holding real secrets, 539 had a commit that modified this file with Claude recorded as co-author, spanning models from Sonnet 4.5 through Opus 5.5. That does not prove Claude typed the secrets, only that it was in the commit.
Once pushed, the files stayed. The median repository had first committed it 217 days earlier, and 118 repositories passed the one-year mark. 211 forks copied the same secrets along, and 734 more secrets across 509 repositories survive only in git history after the file was deleted. Deleting the file does not fix it.
Two Scanners Both Missed 215 of Them
Apiiro ran gitleaks and TruffleHog, the two open source secret scanners most teams reach for, against the 1,122 files. gitleaks caught 564 and TruffleHog 643, and 215 were missed by both, roughly one in five.
The reason is what these passwords look like. Scanners hunt for prefixes such as sk- or AKIA, or long high-entropy strings. A password a human typed into the middle of a command looks like an ordinary word: the value after PGPASSWORD=, sshpass -p, or mysql -p, or an Authorization: Bearer header in a curl command.
The same pattern showed up in other files that record what an agent ran:
| File | Examined | Real secrets |
|---|---|---|
Shared config .claude/settings.json, committed on purpose | 76,011 | 298 files |
| Agent transcripts (.specstory, aider, Cursor exports) | 2,523 | 120 files, 87 repos |
| Agent memory files (MEMORY.md and similar) | 1,200 | 9 repos |
| Handoff and deployment notes | 2,095 | 33 files |
| VS Code Copilot auto-approve settings | 173 | 9 repos |
A third of the secrets found in handoff notes were in notes the agent had written itself. Outside GitHub the picture held: 126 of 31,053 Hugging Face Spaces carried the file, one of them with a database service key.
Staying off GitHub is not safety either. The Shai-Hulud worm that infected npm packages in September 2025 ran TruffleHog on victim machines to harvest secrets, and that scanner flags 643 of Apiiro's 1,122 files. Supply chain attacks aimed at credentials on developer machines keep arriving, including LiteLLM, backdoored again seven months later. To an attacker, one plain-text JSON file is a sorted key ring.
Reported in August 2025, Still Unanswered
This behavior is not newly discovered. In August 2025, issue #5544 on the Claude Code repository reported that approved commands containing credentials are stored verbatim in settings.local.json. It was auto-closed as inactive in January 2026 with no response from Anthropic.
Apiiro lists four related issues, three of them closed as stale or duplicate. Issue #91270, reporting that the VS Code extension writes "always allow" into the shared settings file, was auto-closed for inactivity on November 5, the day the report came out. As of publication there is no public statement from Anthropic.
Two caveats on the report. Apiiro sells security products. And "real secret" means a value matching a known key format or sitting next to a public host, not a credential verified to authenticate; the final classification step combined rule checks with a separate LLM reviewer. The underlying behavior, though, is confirmed by Anthropic's own documentation and by the GitHub issues.
Checking Your Own Repos
This is not gated by plan or region. The file is written by the local CLI, so every Claude Code user is in scope wherever they work, on any plan. Check if any of these apply:
| Situation | Risk |
|---|---|
| You clicked "don't ask again" on a command containing a password or token | It is in settings.local.json on that machine, in plain text |
| That folder became a git repo later, or you cloned it on another machine | The global exclude does not apply, so it can be committed |
| You have told Claude to "commit everything" | The file may have gone in with it |
Your team keeps approval rules in a shared .claude/settings.json | That file is committed by design |
From the repository root, these two commands show whether the file was ever committed and whether a rule currently holds a credential:
git log --all --oneline -- .claude/settings.local.json .claude/settings.json
grep -nE "PGPASSWORD=|sshpass -p|mysql .*-p|Bearer |://[^ ]*:[^ ]*@" .claude/settings.local.json
If either returns anything, rotate the credential first and clean up the files second, because forks and clones already hold copies. Untrack a committed file with git rm --cached .claude/settings.local.json and add the path to the repository's own .gitignore. Going forward, have commands reference $DB_URL style environment variables instead of literal passwords so only the variable name lands in the rule, and approve pattern rules such as Bash(npm run *) rather than verbatim commands.
There is a compliance clock attached if the credential touches personal data. A live database owner password in a public repository is the kind of exposure that Singapore's PDPA requires an organization to assess and, where significant harm is likely or 500 or more individuals are affected, report to the PDPC. The same logic drives GDPR Article 33 notification in the EU.
If you do one thing today, pick a project where you have had Claude Code connect to a database or a server and run that git log command. An empty result means you only have a local file to clean up. Any commit history means every credential that file ever held is now on the rotation list.