Claude Code's 'Don't Ask Again' Option Leaks Passwords in 1,122 Public GitHub Files
Security research firm Apiiro found that Claude Code's 'Yes, and don't ask again' option persists sensitive credentials from config files into saved commands, leaking 2,539 real secrets across 1,994 public GitHub repositories and affecting 63 organizations. Anthropic's Head of Claude Code Boris Cherny responded that the team is investigating mitigations, including auto-mode interception and built-in secret scanning.
Related Entities
Full Report
Contents12 sections
Update, November 8: Anthropic’s Head of Claude Code responds. Boris Cherny responded on Hacker News on November 7 and took part in the discussion through the weekend. He said the team is “looking into what we can do to prevent this,” named approaches it plans to prototype, “making sure auto mode catches this, building in basic secret scanning,” and, when a reader noted the same can happen in auto mode when it asks about a sensitive command, answered “good catch.” Full response below.
Apiiro research found 2,539 real secrets in 1,994 public GitHub repositories: database passwords, cloud keys, API tokens, SSH root logins. Among them: 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. Most belong to individual developers. 63 organizations are affected, from student groups to startups, software agencies and established vendors. One confirmed its key had been live.
Ask Claude Code to check a database or call an API, and the command it proposes carries the secret from your config file. It asks before running it. Pick "Yes, and don't ask again" and it saves that exact command, secret included, to .claude/settings.local.json inside the project folder. Nothing in the repo marks that file as private, so it gets committed with the rest of the code.
Out of 104,185 public copies of this file on GitHub, 1,122 hold a real secret. We found 1,160 more in git history, in the shared settings.json teams commit on purpose, and in agent chat transcripts saved in repos.
Check if you’re affected
Is it public? Search your GitHub organization for .claude/settings.local.json and .claude/settings.json. Each hit is a file anyone can read right now.
Was it ever committed? Check each repo’s git history for the file, even if it’s gone today. If history has it, so does every fork and clone.
What's in it? Find every copy of the file on your machine and read its allow list. Each entry is a command you approved, with whatever you typed into it: look for passwords, tokens, keys and connection strings.
Found something: rotate first, clean up second.
How a secret ends up in a settings file
Developer machines hold secrets: a database connection string in a config file, cloud keys in local installations, an API token in .env. Ask Claude Code to check why login fails on staging or to run a migration, and the command it proposes carries that secret, because it can’t work without it. Claude Code asks before it runs a shell command, multiple times a session. After the tenth interruption, most stop reading commands, and a secret is one word in a long line:

Pick "Yes, and don't ask again" and it runs the command and adds a permission rule to .claude/settings.local.json in the project folder, so it won't ask again. The rule is the command string itself:

This is Claude Code's own behavior, not the model's: it happens with Anthropic's latest models too, and we reproduced it with Opus 5.5 and Fable 5.1.
The file is meant to stay on the developer’s machine, and Claude Code tries to keep it there. When it creates the file inside a git repo, it adds it to the developer's global git ignore list. That covers the common case. It doesn’t cover a folder that becomes a repo later, a clone on another machine, or a file someone already committed. The rule never goes into the repo's own .gitignore, so nothing travels with the project to protect it.
Claude Code does notice when the file is already tracked by git: the permissions docs say a tracked copy is treated as repository-supplied, and its debug log records “is tracked in the index; gitignore rules do not apply to tracked files.” The user is not told, and the next approval is appended to the tracked file.
Often Claude commits the file itself. In 539 of the 1,105 repos with a real secret that we traced, a commit co-authored by Claude changed the file. Those commits name every recent model, from Sonnet 4.5 to Opus 5.5. Claude Code’s commit instructions tell the model not to commit .env or credentials.json. Its own settings file is not on that list.
Who is exposed
63 organizations hold a real secret in a public allowlist. The strongest cases, all in .claude/settings.local.json and each checked at a pinned commit:
| Organization | What’s exposed |
|---|---|
| Database vendor | Its own cloud API key with manage access and no expiry claim, plus the cluster host |
| B2B startup | Production Azure Postgres password |
| Software agency | Square production access token |
| Open-source project (over 1,000 stars) | OpenAI-format API key |
| Open-source project | npm token |
| IT services firm (medical-records app) | Owner password for the app’s cloud Postgres database |
| Payments startup | Postgres password for the postgres role |
They range from student and hackathon groups to startups, software agencies and IT services firms. A few are established vendors, exposed through their own demo and workshop repos. Nobody meant to publish a key. The key was in a command, the command was approved, and the file was committed with everything else.
The allowlists also hold server logins: 43 SSH credentials for public servers, some of them a root password in an sshpass command. One university repo, for example, permanently approved a root SSH command to a public server.
How many
Public GitHub holds 104,185 copies of .claude/settings.local.json, in 103,617 repositories. 1,122 files (1.1%) hold a real secret: a key in a known provider format, or a password or token next to a public host. Together they hold 1,379 distinct secrets: 636 provider keys and 743 passwords or tokens for public hosts.
More than a third open a database directly: 379 database passwords and 122 Supabase service-role keys. Another 103 are Supabase account tokens, which control every project in the account. The rest are mostly API tokens for third-party services and AI model keys, plus 43 SSH logins, 42 GitHub, GitLab and npm tokens, 23 AWS keys and 6 private keys.

Large allowlists drive the rate. One in ten files over 8 KB holds a real secret, against fewer than one in 500 under 500 bytes. The longer a developer has been clicking “don’t ask again”, the more the file holds.

The files are still there: every one sat on its repo’s default branch on November 2, 2026, and most have sat there a long time. In the median repo with a real secret, the file was first committed 217 days before that. In 118 repos, more than a year before. Forks copy them: 211 forks of 74 repos carry the same secrets.
Deleting the file doesn’t solve it. Earlier versions of the file hold 734 real secrets, in 509 repos, that appear in no current copy, usually because the file was deleted.
Counting the file's history, the shared settings file and agent transcripts (next sections), the total comes to 2,539 distinct real secrets in 1,994 repos.
What secret scanners miss
Generic secret scanners miss many of these. We ran gitleaks and TruffleHog over all 104,185 files. Of the 1,122 files with a real secret, gitleaks flagged 564 and TruffleHog 643; 215 were flagged by neither.
The gap is passwords inside commands. Scanners look for key formats: a provider prefix, a long random string. A password typed after PGPASSWORD=, sshpass -p or mysql -p, or a bearer header in a curl call, is an ordinary word in an ordinary command line, and both tools mostly let it through.

This matters beyond this file. The same password-in-a-command pattern appears wherever an agent records what it ran: transcripts, memory files, handoff notes, and a scanner tuned to key formats misses it in all of them.
Not just one file
The allowlist is the clearest case, but agents write secrets into other files developers commit.
| File | Checked | With a real secret |
|---|---|---|
| Shared .claude/settings.json | All 76,011 | 298 files |
| Agent chat transcripts (.specstory, aider, Cursor exports) | 2,523 | 120 files in 87 repos |
| Agent memory files (MEMORY.md and similar) | 1,200 | 9 repos |
| Handoff and deploy notes | 2,095 | 33 files |
| VS Code Copilot auto-approve settings | 173 | 9 repos |
Teams commit the shared settings file on purpose, and most of its secrets sit in allow rules as exact command lines. A third of the handoff notes with a secret were written by the agent itself.
The file leaks beyond GitHub too. Of 31,053 Hugging Face Spaces, 126 hold .claude/settings.local.json, and one has allow rules with a database service key and a user password. On GitLab.com, 2 of the 69 public copies we checked hold a real secret, including a GitLab access token.
The habit that leaks is the same everywhere: typing a secret into a command that an agent then records.
On the developer's machine
Most of these files never reach GitHub. They stay on developers’ machines, and that doesn’t make them safe. The allowlist is plain JSON in the project folder.
Malware already collects credentials from developer machines in bulk. In September 2025 the Shai-Hulud npm worm downloaded TruffleHog and ran it over the victim’s files. That scanner flags 643 of the 1,122 files with a real secret. Three weeks earlier, the malicious Nx packages told the developer’s own Claude Code and Gemini CLI to search the disk for secrets.
The file can also leave without git: in a published npm package, a Docker image built with a copy command, a zip archive or a synced folder. And a secret approved once stays in the file until someone deletes the rule, long after the command ran.
Prior work
This post adds the full GitHub count of secrets leakage at scale, the organization cases, the scanner gap, and the other agent files that carry the same secrets. Claude Code users have reported the mechanism in GitHub issues since August 2025 (#5544, #11982, #13106, #91270). None got a reply from Anthropic, and three were closed automatically as inactive or duplicate. ironPeak found the same file in their own repo in February 2026 and measured 2.4% of repos with AI config folders carrying secrets in history, on a sample of 100. Lakera found credentials in 33 such files across 30 npm packages in April.
What to do
Developers:
- If the file is tracked in a repo, untrack it with git rm --cached
.claude/settings.local.jsonand add it to the repo’s own .gitignore. - Rotate every credential the file has ever held. Removing it doesn’t clear git history, forks or clones.
- Even if the file was never committed, open it and delete every rule that contains a secret.
- Stop typing secrets into commands. Reference them as DB_URL, not the secret.
- Approve patterns, like
Bash(npm run:*), instead of literal commands.
Security teams:
- Treat agent folders: .claude/, .cursor/, .gemini/, .specstory/, agent memory files, as secret-bearing, like .env, on laptops as well as in repos.
- Add them to pre-commit and CI secret scanning, including history. Make sure the scanner catches passwords inside commands (PGPASSWORD=, sshpass -p, mysql -p, bearer headers), not only provider key formats.
- Add .claude/settings.local.json to your org’s .gitignore templates.
- Triage credentials paired with public hosts first: those are the ones that give access.
Anthropic’s Head of Claude Code responds
We shared this research with Anthropic before publication. After it went live, Boris Cherny, Anthropic’s head of Claude Code, responded on Hacker News on November 7 and posted ten comments over the weekend.
Historically Claude Code has not done secret scrubbing (there are many good tools for that), but we are looking into what we can do to prevent this.
On the approach:
There’s a few possible approaches: making sure auto mode catches this, building in basic secret scanning, a few other ideas. Going to prototype a few of these to understand the tradeoffs better before we ship something.
When a reader noted that the same can happen in auto mode when it asks about a sensitive command:
Yeah good catch. Thinking through what we can do to improve this (ideas welcome).
He also said Claude Code gitignores the file when it creates it, so in his view the exposed copies were created manually and checked in; recommended auto mode over permission rules; and recommended enabling the secret scanning that GitHub and other hosts offer.
Disclosure
We reported each organization case to its owner on November 2 and 3, 2026. We also notified Anthropic through its requested disclosure channel and several others.
Method and limits
Collection. All data came from read-only GitHub code and commit search on default branches, November 1 to 3, 2026. Code search returns at most 1,000 results per query, so we split the search by file size until every slice fit under the cap. That listed 104,185 .claude/settings.local.json files in 103,617 repos and 76,011 shared settings.json files, and we downloaded every one. File history covers 43,120 repos, including every repo whose commits mention removing, untracking, redacting or rotating the file, so the history count is a floor. Forks: every fork of a repo with a real secret. Transcripts, memory files, handoff notes and Copilot settings were found by searching for key prefixes and connection strings; the table gives how many we checked. We compared how 16 coding agents store approvals from their documentation; Claude Code is the only one confirmed to write the full approved command to a project file by default.
Classification. We use the two detector classes secret scanners use. Provider patterns match a known key format: OpenAI, Anthropic, AWS, GitHub, npm, Supabase, Stripe, Slack and others. Generic secrets are passwords and tokens without a known format; we count one only when a public host sits on the same line, as in a connection string or a PGPASSWORD= before psql -h. Rules then remove known false positives: placeholders, common default passwords, local and private hosts, keys that are public by design (Supabase anon keys, Firebase web config), the local Supabase demo key, expired tokens, and GitHub and npm tokens whose built-in checksum fails. Every remaining distinct value, 2,774 in all, was reviewed in its masked context by an independent LLM reviewer working from a written rubric. A value counts as a real secret only when the rules and the review agree: 2,539 across all sources. Memory files, handoff notes and Copilot settings were classified by the rules alone. gitleaks and TruffleHog ran without verification.
Limits. No credential was used or tested, and no host was contacted. "Real secret" means a credential that matches a provider format or points at a public host, not one known to be valid. Every organization case was checked at a commit-pinned link.