One click in Claude Code — "Yes, and don't ask again" — has been quietly saving developers' real passwords and API keys into a file that then ended up on public GitHub. Security firm Apiiro found 1,122 public copies of that file holding at least one real secret, including a database vendor's own admin-level cloud key, a production Azure Postgres password, a Square production token, and the owner password of a medical-records database.
Counting old versions in git history, shared settings files, and saved agent chat logs, the total reaches 2,539 secrets across 1,994 repositories. The behaviour was first reported in August 2025 and never fixed. If you use Claude Code, or any AI coding agent, this article explains how the leak works, how to check whether your own repositories are affected, and how to clean it up properly — because deleting the file alone does not undo the damage.
| What Apiiro found (Nov 5, 2026) | Number |
|---|---|
Public copies of .claude/settings.local.json on GitHub |
104,185 in 103,617 repos |
| Copies holding at least one real secret | 1,122 (1.1%) |
| Distinct secrets in those files | 1,379 |
| Database passwords among them | 379 |
| SSH logins / GitHub, GitLab and npm tokens / AWS keys | 43 / 42 / 23 |
| Total secrets incl. git history, shared settings, chat logs | 2,539 in 1,994 repos |
| Organisations affected | 63 |
| Files flagged by neither gitleaks nor TruffleHog | 215 |
How one click saves your password
The mechanism is ordinary, which is what makes it dangerous. You ask Claude Code to check a row in your staging database or call an API. It proposes a shell command, and the command carries the secret — a password pulled from your config file, sitting right there after something like PGPASSWORD= or sshpass -p. Claude Code asks before running the command, as it should.
You pick "Yes, and don't ask again" because you are going to run this command all day and the prompt is annoying.
That choice does two things. It runs the command, and it saves the command as an "allow" rule so future matching commands run without asking. The rule is the command string itself, secret included, and it is written to .claude/settings.local.json inside the project folder. The file is meant to stay on your machine — it holds your personal, per-project settings. But nothing in the repository marks it as private, so when you commit your work, the file goes with it.
Anyone who can read the repository can now read your database password.
Apiiro's research, published on November 5, 2026, is blunt about whose behaviour this is: "This is Claude Code's own behavior, not the model's." The researchers reproduced it with Anthropic's latest models, Opus 5.5 and Fable 5.1, and they compared the documentation of 16 coding agents. Claude Code was the only one confirmed to write the full approved command to a project file by default. This is not a prompt-injection attack or a jailbreak.
It is a product design choice meeting an ordinary workflow.
Why the usual protection did not stop it
Claude Code does have a protection, and it is worth understanding why it is not enough. The first time Claude Code writes the file inside a git repository, it adds the file to your global git excludes list, so it stays out of commits. That covers the common case — a project that is already a repository when you first use the tool in it.
Apiiro found the gaps around that case, and they are exactly the gaps real developers fall into.
The protection does not cover a folder that becomes a repository later. Start a project, use Claude Code in it for weeks, then run git init and push: the file was already there, and the global exclude was never added for that path. It does not cover a clone on another computer, where the global excludes file is different or missing. It does not cover a file that was already committed before the protection existed.
And the rule never goes into the project's own .gitignore, which is the file that actually travels with the repository and protects every teammate who clones it.
The numbers show how often those gaps were hit. In 539 of the 1,105 leaking repositories Apiiro traced, a commit co-authored by Claude had changed the settings file — the agent itself was involved in committing the file that held the secret. In the median leaking repository, the file had been committed 217 days before Apiiro's November 2 snapshot, which means most of these secrets sat in public for months.
And there is a second file to worry about: approvals are sometimes written to the shared .claude/settings.json instead, a file teams commit on purpose, and Apiiro found secrets in 298 of its 76,011 public copies.
What was actually in the files
More than a third of the secrets open a database directly, including 379 database passwords. The rest include 43 SSH logins for public servers, 42 tokens for GitHub, GitLab and npm, and 23 AWS keys. The headline cases Apiiro names are the kind that keep security teams awake: a database vendor's own admin-level cloud key, a production Azure Postgres password, a Square production token, and the owner password of a medical-records database.
Sixty-three organisations are affected, mostly software companies of all sizes, and one company Apiiro notified confirmed that its key had been live. An independent summary of the findings covers the same numbers and adds useful context on how the researchers decided what counted as a secret.
Two caveats matter, and Apiiro states them plainly. The researchers did not test or use any credential they found, and they did not contact any host, so the counts show exposure risk, not demonstrated compromise. A value counted as a secret when it matched a known provider format, or when a password or token sat next to the address of a public server, with an AI reviewer agreeing.
The figures are a floor for public GitHub, collected by code search between November 1 and 3 — not a measure of how many credentials still work, and not a count of private repositories, where the same file sits in plain text on every laptop that clicked "don't ask again".
That last point is the one most coverage misses. GitHub is only where the leak could be counted. The file exists on the machine of everyone who approved a command containing a secret, whether they committed it or not.
Malware already harvests credentials from developer machines in bulk — the Shai-Hulud npm worm ran TruffleHog over its victims' files — so a plaintext password sitting in a known location on disk is exposed even if it never reaches a public repository.
How to check whether you are affected
Start with the public surface, because it is the fastest check and the one with the worst consequences. Search your GitHub organisation for .claude/settings.local.json and .claude/settings.json. Every hit is a file anyone on the internet can read right now, and each one needs to be treated as a live leak until you prove otherwise.
Check the git history of each repository too, not just the current files: a secret removed from the latest commit is still sitting in an earlier one, and in every fork made before the removal.
Then check your own machine and your team's. Look for the file in every project folder where Claude Code has been used, including projects that were never committed and folders that became repositories later. If you share a machine or a dotfiles setup with teammates, check theirs as well — the global git excludes protection is per-machine, so a teammate's clone may have committed a file your machine would have excluded.
Run a secret scanner over your repositories, but know its limits before you trust a clean result. Apiiro ran gitleaks and TruffleHog over all 104,185 public copies of the file: gitleaks flagged 564 of the 1,122 files holding secrets, TruffleHog flagged 643, and 215 were flagged by neither.
That is nearly one in five leaking files that both scanners missed, usually because the secret is a password typed inside a command — after PGPASSWORD=, sshpass -p, or mysql -p — with no provider prefix for a pattern to match. A scanner that finds nothing has not proven you are safe. Search for the filenames themselves, and read any hits by hand.
Best secret-scanning tools to check your repos
If you are choosing a scanner, the honest comparison starts with what Apiiro measured. TruffleHog caught more of these files than gitleaks — 643 against 564 out of 1,122 — and both are free and open source, which makes them the obvious first choice for any team. Neither is a complete answer on its own, because both work mainly by matching known patterns: provider key formats, recognisable token shapes, entropy checks.
A password typed into the middle of a shell command has none of those signals, which is exactly why 215 files slipped past both.
The practical setup is to use both, not one, and to add a filename search on top. Run gitleaks and TruffleHog across your repositories and your git history, then separately search for .claude/settings.local.json and .claude/settings.json in every repository you own, public or private, and read whatever you find.
GitHub's own secret scanning and push protection are worth enabling as a backstop — they catch known provider formats at push time — but they have the same pattern-matching blind spot for passwords inside commands. The best tool for this particular leak is still the simplest one: searching for the filename.
For ongoing protection, the scanners belong in your CI pipeline, not just in a one-off audit. A pre-commit hook running gitleaks stops most accidental commits before they happen, and a scheduled scan of your organisation catches the files that were committed before the hook existed.
Neither replaces the habit that actually prevents this leak, which is keeping secrets out of command lines in the first place — but as a safety net, two scanners plus a filename search is the best free setup available right now.
How to clean up if you find a secret
Rotate first, clean up second. The moment you find a leaked credential, assume it has been seen and revoke or replace it before you touch the repository. Change the database password, revoke the API token, rotate the AWS key. Only after the old credential is dead should you remove it from the repository — cleaning the file first while the credential is still live leaves a window in which anyone who already copied it can still use it.
When you do rotate, generate a strong replacement password rather than reusing a variation of the old one, and store it in a proper secrets manager or environment file, never in a command.
Removing the file from the current commit is not enough. Git history keeps every version, and forks keep their own copies, so a secret that was ever committed is still public until the history itself is rewritten. For a single repository, rewrite history with a tool like git filter-repo or BFG Repo-Cleaner, force-push the cleaned history, and then ask GitHub support to purge the cached copies.
For a secret that spread to forks, contact the fork owners — or accept that the credential must stay revoked forever, which is another reason rotation comes first.
After the cleanup, close the hole that let it happen. Add .claude/settings.local.json to the project's own .gitignore, so every teammate's clone is protected instead of relying on each machine's global excludes. Add the same entry to your global gitignore as a second layer. And check the shared .claude/settings.json for any approved commands that contain secrets — that file is committed deliberately, so anything in it is public by design.
How to stop it happening again
The real fix is a habit change, not a tool. Never put a secret in a shell command. Use environment variables, a .env file that is gitignored, or your database client's config file — all of which keep the credential out of the command string that Claude Code saves. When Claude Code proposes a command that contains a password, reject it and ask for a version that reads the secret from the environment instead.
That one refusal is worth more than any scanner, because a secret that never enters a command can never be saved as an allow rule.
Two more habits close the remaining gaps. First, treat "don't ask again" as a decision with a permanent record, not a convenience click: before approving it, read the full command and ask whether any part of it would be a problem if it were published. Second, audit your allow rules occasionally.
Open .claude/settings.local.json and read what is in it — if you find a password, a token, or a host address you would not want on GitHub, it is already too late to prevent the save, but it is not too late to rotate the credential and fix the rule.
It is worth noting that users reported this behaviour on Claude Code's GitHub tracker as early as August 2025. The original report, filed on August 11, 2025, warned that commands approved with API keys and tokens were saved verbatim in the file. Apiiro cites four such reports and says none received a reply from Anthropic; three were closed automatically as inactive or duplicates, and the 2025 report was closed by a bot as "not planned" on January 3, 2026.
As of the research publication, Anthropic had not responded publicly. Do not wait for a product change — the fix is yours to make, and it starts with checking your own repositories today. This is the second Claude Code privacy issue we have covered, after Claude Code's earlier email leak sent users' email addresses to websites, and the pattern is the same: a convenience feature with a quiet side effect that only becomes visible when someone goes looking.
The broader lesson applies to every AI coding tool, and our guide to keeping secrets out of AI tools covers the same discipline for API testing.
Frequently asked questions
How did Claude Code leak passwords to GitHub?
When you pick "Yes, and don't ask again" on a command Claude Code proposes, it saves the full command — secret included — as an allow rule in .claude/settings.local.json inside the project folder. If that file is committed to a public GitHub repository, anyone can read the secret. Apiiro found 1,122 public copies of the file holding at least one real secret.
How do I check if my GitHub repos leaked secrets?
Search your GitHub organisation for .claude/settings.local.json and .claude/settings.json, and check the git history of each repository, not just the current files. Then search your own machine for the same filenames in every project folder. Run gitleaks and TruffleHog as well, but do not trust a clean scan alone — both scanners missed 215 of the 1,122 leaking files Apiiro found.
What should I do if I find a leaked password or API key?
Rotate it first: change the database password, revoke the API token, or rotate the cloud key before touching the repository. Only then remove the file and rewrite the git history with a tool like git filter-repo or BFG Repo-Cleaner, force-push, and ask GitHub support to purge cached copies. Deleting the file without rotating leaves the credential live in history and forks.
Does deleting .claude/settings.local.json fix the leak?
No. Deleting the file removes it from the latest commit, but every earlier version stays in git history and in any forks made before the deletion. The leaked credential must be revoked first, and the history must be rewritten, or the secret remains public in the old commits even after the file is gone.
What are the best secret-scanning tools for this leak?
TruffleHog and gitleaks are the best free options — both are open source, and Apiiro measured TruffleHog catching 643 of the 1,122 leaking files against gitleaks' 564. Use both, and add a direct search for the filenames .claude/settings.local.json and .claude/settings.json, because 215 leaking files were flagged by neither scanner. Enable GitHub's secret scanning and push protection as a backstop.
What is the best password manager for developers?
There is no single best choice, and the right answer depends on your team. What matters is that secrets live in a manager or vault — or in environment variables loaded from a gitignored file — and never in shell commands, chat logs, or settings files that get committed. A password manager solves the storage problem; the habit of never typing a secret into a command solves the leak.
Use both together, and generate fresh, unique passwords for every service you rotate.