Claude Code “Don’t Ask Again”: The Setting That Leaked 2,539 Secrets to GitHub
Key Takeaways
- In Claude Code, choosing "Yes, and don't ask again" on a permission prompt saves the exact command you approved as an allow rule in `.claude/settings.local.json` inside your project folder.
- If that command contained a password, API key or token, the secret is saved with it, in plain text.
- Security firm Apiiro, in research published on 5 November 2026, found 1,122 public copies of that file on GitHub holding at least one real secret, and 2,539 secrets in total once git history, shared settings and agent transcripts were counted.
- Claude Code tries to protect the file by adding it to your global git excludes list, but that protection only works on your machine. It does not travel with the project, and it cannot help a file that was already committed or a folder that becomes a repository later.
- The fix is not to stop using the feature. It is to never type secrets into commands, to use wildcard allow rules instead of exact commands, and to check your own repositories for the file now.
- Search interest in the phrase "claude code dont ask again risk" rose sharply in the US over the past seven days, according to the Google Trends signal that surfaced this story — the week Apiiro's research was published.
What "Don't Ask Again" Actually Does
Claude Code is Anthropic's AI coding assistant. It works in your terminal, reads your code, edits your files and runs shell commands for you. Because running commands on your machine is powerful and potentially destructive, Claude Code asks for permission first. Before it runs most shell commands, edits a file or fetches a web page, a prompt appears, and you decide whether to allow it.
The prompt gives you more than one option. You can approve the action once, or you can pick "Yes, and don't ask again." The second option is the one this article is about, and it does exactly what it says: it approves the command and tells Claude Code not to ask about it again.
What many developers do not realise is how that choice is remembered. Claude Code does not store a vague memory that you trust a certain kind of command. It writes an allow rule — the exact command text, word for word — into a settings file called `.claude/settings.local.json`, inside your project folder. The next time Claude Code wants to run that command in that repository, it checks the file, finds the rule, and runs it without asking.
For a harmless command like `npm run test`, that is convenient. It is the tenth time you have approved the same test run, and you are tired of being interrupted. For a command that contains a secret, it is a leak waiting to happen — because the secret is part of the command, and the command is now saved in a file.
This is not a bug in the usual sense. Claude Code saved what you approved. The problem is that what you approved had a password inside it, and the file it was saved to is an ordinary file in your project, subject to all the ordinary ways files end up somewhere they should not be.
Where the Rule Is Saved, and Why That Location Matters
When you pick "Yes, and don't ask again," the allow rule is normally written to `.claude/settings.local.json` at the root of your git repository, and it applies to future sessions anywhere in that repository. That is how most developers' local settings files get created: they never open the file, it fills itself up, one approval at a time.
Two limits are worth knowing, because they explain a lot of the confusion around this feature.
First, not every approval is saved the same way. A Bash command approval, a WebFetch domain approval or a WebSearch approval persists to the file. A file edit approval, by contrast, lasts only until the session ends; it is never written to a file. That is the most common reason approvals seem to "forget" themselves: if it was an edit, the approval was never meant to stick.
Second, a compound command is not saved as one rule. For a command like `git status && npm test`, Claude Code saves a separate rule for each part that needed approval — up to five — so `npm test` is recognised next time whatever precedes it. And sometimes the prompt offers only a one-time yes: Claude Code withholds the permanent option when it cannot show you everything the rule would allow. In that case, you can add the rule yourself with the `/permissions` command.
The file itself is meant to stay on your machine. Anthropic's documentation describes a protection: the first time Claude Code writes the file in a git repository that does not already ignore it, it adds a double-asterisk glob ignore rule for `.claude/settings.local.json` to your global git excludes file — the file git consults on your machine for patterns to ignore in every repository, usually `~/.config/git/ignore`. On paper, that keeps the file out of your commits.
In practice, as Apiiro's research showed, that protection has holes. And the holes are the story.
What Apiiro Found on GitHub
Apiiro is a security company that sells products to protect applications and coding agents. On 5 November 2026, its researchers Shmulik Cohen and Matan Giladi published research titled "Coding Agents Are Leaking Your Secrets to GitHub." They had searched public GitHub repositories between 1 and 3 November 2026 for copies of `.claude/settings.local.json`, and what they found turned a quiet design quirk into a headline. The figures in this section come from Apiiro's research as reported in independent coverage, including VandaTeam's detailed write-up and Aighten's report.
They examined 104,185 public copies of the file across 103,617 repositories. Of those, 1,122 copies — about 1.1% — contained at least one real secret, with 1,379 distinct secret values between them. When the researchers widened the search to include git history, shared settings files and agent transcripts, the total rose to 2,539 distinct secrets across 1,994 repositories.
The kinds of secrets matter as much as the count. Database access dominated: 379 database passwords, plus 122 Supabase service-role keys and 103 Supabase account tokens, according to summaries of the research. There were also 43 SSH login credentials, some containing server root passwords, 42 GitHub, GitLab and npm tokens, and 23 AWS keys, along with cloud platform credentials and private keys.
A few more findings from the research are worth stating, because they show how the leak spreads beyond a single careless commit:
- 734 secrets existed only in older commits, in git history. Deleting the file today does not remove those copies.
- 211 forks carried copies of the leaked files, so the secret spread to repositories the original developer never touched.
- Of the 1,122 files holding a real secret, the secret-scanning tool Gitleaks flagged 564 and TruffleHog flagged 643 — and 215 slipped past both, mostly passwords typed inside commands rather than keys in a recognisable format.
- In 539 of the 1,105 repositories Apiiro traced, a commit co-authored by Claude itself had touched the settings file. That does not prove Claude pushed the secret — a co-authored commit is not proof of who pushed what — but it shows how easily an agent can be part of the chain that moves the file into a public repository.
- Apiiro reproduced the behaviour with both Opus 5.5 and Fable 5.1, Anthropic's most recent models at the time, confirming that the leak is a property of the tool, not of a particular model.
Two caveats from the research deserve equal prominence, because they are the difference between a scary number and an accurate one. Apiiro did not test any credential or contact any host, so the number of credentials still valid is unknown. The only confirmation that a leaked key was live came from a single company Apiiro notified. And the count of 2,539 rests in part on the judgement of an automated reviewer, not on a manual check of every secret — no third party has independently repeated the counts. The research shows exposure risk, not demonstrated compromise. That is still serious: a database password sitting in a public repository is a problem whether or not anyone has used it yet.
It is also worth noting that this was not the first warning. A GitHub issue opened in August 2025, issue #5544, described approved commands with credentials being stored verbatim in `settings.local.json`. As of the reporting available when this article was written, no public statement from Anthropic on Apiiro's findings had been reported, and the current documentation still describes the global-excludes approach.
Why the Gitignore Protection Does Not Always Protect You
The global git excludes file is the heart of the problem, because it is a protection that works in the common case and fails in the cases that matter.
When Claude Code creates `.claude/settings.local.json` inside a git repository, it adds the ignore rule to your global excludes — your machine's own ignore list. That covers the normal flow: you are working in a repository, you approve a command, the file is created, and git on your machine ignores it. If you commit and push, the file stays behind.
But the rule never goes into the repository's own `.gitignore`, so nothing travels with the project to protect it. That leaves at least four gaps, all described in the coverage of Apiiro's research:
A folder that becomes a repository later. If you start a project in an ordinary folder, approve commands there, and only initialise git afterwards — or only push it to GitHub later — the ignore rule may not have been added at the time the file was created, or the file may already exist before git is involved at all.
A clone on another machine. The global excludes file lives on your computer. When a teammate clones the repository on theirs, your ignore rule does not come with it. If the file was committed by mistake, it is in the repository for everyone.
A file someone already committed. Git's ignore rules do not apply to files that are already tracked. Once `.claude/settings.local.json` has been committed, adding it to any ignore file afterwards changes nothing. The file stays in the repository until someone explicitly removes it from tracking — and removing it from the current commit does not remove it from history.
A file committed by the agent itself. Claude Code can commit and push code on your behalf. If it commits the settings file as part of a batch of changes, the file is public before you have looked at the commit. The finding that 539 of 1,105 traced repositories had a Claude co-authored commit touching the file shows how plausible that path is, even if it does not prove Claude pushed any particular secret.
There is a fifth, simpler gap: the protection assumes you are working in a git repository at all. If the folder is not a repository, there is no gitignore of any kind, and the file sits in the project like any other file — ready to be copied, zipped, shared or uploaded by whatever you do with the project next.
None of this means the global-excludes protection is useless. It catches the most common case. But a safety measure that catches the common case and misses the edge cases is exactly the kind of measure that produces a research paper full of leaked secrets: most developers are protected, and a meaningful minority are not.
The Other Risk: Approvals That Are Too Broad
The secret leak is the headline risk of "don't ask again," but it is not the only one. The same feature can also quietly widen what Claude Code is allowed to do without asking you, and the widening is easy to miss because it happens one small approval at a time.
An allow rule with no wildcard matches one exact command. That is narrow, and it is the safest form of the feature. But developers who get tired of approving similar commands often graduate to writing their own rules, and that is where the danger grows. A rule like `Bash(npm run )` allows any npm script. A rule like `Bash(git )` allows every git command, including `git push` and commands that run a program you name. A bare `Bash` allow removes the gate entirely.
The permission system does have a backstop: rules are checked in order, deny first, then ask, then allow, and the first match wins. A deny rule beats an allow rule at any level, and an allow rule cannot carve an exception out of a deny rule. So a careful developer can pair broad allows with specific denies — for example, allowing `Bash(npm run )` while denying `Bash(rm -rf )` and `Bash(curl *)`. But that backstop only helps if someone actually writes the deny rules, and most developers never do.
There is also the question of modes. Claude Code has several permission modes: `default` (Manual), where it asks for each action; `acceptEdits`, which auto-approves edits and common filesystem commands; `plan`, for planning without acting; `auto`, where a separate classifier model approves actions; `dontAsk`, which refuses anything that would have prompted; and `bypassPermissions`, which skips prompts and safety checks. Anthropic's documentation says `bypassPermissions` should only be used in isolated environments like containers or virtual machines where Claude Code cannot cause damage, and deny rules still block in every mode, including `bypassPermissions`. Since version 2.1.283, according to documentation coverage from October 2026, auto mode is the starting mode for interactive terminal and VS Code sessions — which means many developers are now running with a classifier, not a human, making approval decisions by default. That makes the rules you have saved, including the ones "don't ask again" wrote for you, more important, not less: they are the standing permissions the classifier works within.
The common thread is that every one of these mechanisms is a trade between convenience and control, and "don't ask again" is the mechanism that trades control away most quietly — one click, one saved command, no ceremony.
How to Use "Don't Ask Again" Safely
You do not have to stop using the feature. You have to use it the way it was designed: for commands that are safe to repeat, that contain no secrets, and that you have actually read. Here is a practical routine.
1. Never type a secret into a command Claude Code runs. This is the single rule that matters. If a command needs a password, token or key, do not put it on the command line. Reference it as a variable from your secrets manager or environment instead — for example, read the password from an environment variable rather than typing it after `PGPASSWORD=`. If a secret never enters a command, no setting can leak it. If you are about to approve a command and you can see a credential in it, stop. Approve it once, if you must run it at all, and never pick "don't ask again" for it.
2. Read the command before you approve it. Apiiro's own write-up notes that after the tenth interruption in a session, most developers stop reading the commands closely. That is the moment the feature becomes dangerous. If you are approving on autopilot, you are not approving — you are waving things through. Slow down for any command you have not seen before, and for any command that touches the network, the filesystem outside the project, or a database.
3. Prefer wildcard rules you write yourself. Instead of approving exact commands one at a time and letting the file fill up with literal text, write allow rules on purpose in a shared settings file. A rule like `Bash(npm run test )` saves the pattern, not the password. Put the wildcard after the subcommand: `Bash(git commit )` allows commits, while `Bash(git *)` allows every git command, including ones that can run arbitrary programs. You can view and edit your rules with the `/permissions` command, which lists every rule together with the settings file it came from.
4. Put your deny rules in the shared project file. Deny rules win over allow rules, and a deny in the committed `.claude/settings.json` protects every clone of the project. At a minimum, deny reads of secret files — `Read(.env)` and a deny rule covering everything under `./secrets/` — and deny destructive commands such as `Bash(rm -rf )`, `Bash(git push –force )` and `Bash(git reset –hard )`. A deny rule in the shared file cannot be undone by an allow rule a teammate saves locally, and deny rules apply immediately, even before a teammate accepts the workspace trust dialog for the folder.
5. Keep the dangerous modes out of daily work. Use `bypassPermissions` only inside a container, never on your own machine. If you want fewer prompts, `acceptEdits` mode is the safer step up from Manual, because it auto-approves edits and common filesystem commands while still asking about the rest. Reserve `auto` mode for sessions where you understand that a classifier, not you, is approving actions.
6. Check the file regularly. Open `.claude/settings.local.json` in your projects and look at what is in it. If you see a command containing a credential, treat it as a leak: rotate the credential immediately, remove the rule, and check whether the file was ever committed. Make this part of a monthly routine, not a one-off panic after reading a news story.
How to Check Whether You Have Already Leaked Something
If you have used Claude Code, and especially if you have used "don't ask again," it is worth spending ten minutes checking. Here is a practical sequence, drawn from the advice published alongside the Apiiro research.
Search your GitHub organisation. Search GitHub for `.claude/settings.local.json` and `.claude/settings.json` in your organisation's repositories. Each hit is a file anyone can read right now, if the repository is public. Also search git history, not just the current files: 734 of the secrets Apiiro counted existed only in older commits, so a clean current file does not mean a clean history.
Check your local files. Look at `.claude/settings.local.json` in every project you have used Claude Code in. Search it for passwords, tokens and keys. If you find one, the credential is compromised from the moment the file left your machine — rotate it before you do anything else.
Rotate, then clean. If a secret was exposed, rotate it first. Then remove the file from tracking with `git rm –cached`, add it to the repository's `.gitignore` as well as your global excludes, and clean the history if the repository is public — bearing in mind that history rewriting is disruptive on shared repositories, and that forks may already carry copies. Apiiro found 211 forks carrying copies, so assume a leaked secret has spread and rotate it regardless of whether you can delete every copy.
Stop the leak at the source. After cleaning up, change the habit that caused it: no secrets in commands, wildcard rules instead of exact ones, and deny rules for secret files in the shared settings file. A cleanup without a habit change is a cleanup you will repeat.
Use a scanner, but do not rely on it alone. Gitleaks flagged only 564 of the 1,122 secret-bearing files Apiiro found, and TruffleHog flagged 643. Both missed 215 files, mostly passwords typed inside commands. Scanners help, but a manual look at the file catches what pattern matching misses.
What to Do Instead of Approving Everything
The reason "don't ask again" is so popular is that the prompts are genuinely annoying. Approving the same test command for the tenth time in a session feels like busywork, and it is. The answer is not to suffer the prompts or to surrender to them — it is to set up permissions once, deliberately, so the prompts you do see are the ones worth seeing.
Start with the shared project file, `.claude/settings.json`, which is committed to git and applies to the whole team. Put your allow rules there, written as patterns: `Bash(npm run test )`, `Bash(npm run lint )`, `Bash(git status)`, `Bash(git diff *)`. Put your deny rules there too, for secrets and destructive commands. That file is the team's security policy, and because it is committed, it travels with the project — unlike the local file, which does not. For a full walkthrough of writing these rules, see ClockedCode's guide to allowing commands safely.
Use the local file, `.claude/settings.local.json`, for your own exceptions, and treat it as personal, not shared. If you find it filling up with exact commands you approved in a hurry, that is a sign to move the good ones into the shared file as patterns and delete the rest.
Use `/permissions` to review what is actually in force. The dialog shows every rule and which settings file it came from, which is the only reliable way to see the standing permissions you have accumulated — including the ones "don't ask again" wrote for you while you were not looking.
And if you want fewer prompts without giving up oversight, consider `acceptEdits` mode for routine coding sessions, or `auto` mode where a second model reviews each action. Neither is a substitute for good rules, but both are better than clicking "don't ask again" on every prompt until your settings file is a diary of everything you have ever typed.
For a wider view of how Claude's safety behaviour has been questioned this year, see our coverage of Anthropic's Claude submitting a fake police tip and Anthropic's new Claude rules. And if you work with Claude in the browser or in extensions, our Claude Code extension security check covers a different way an AI coding tool can go wrong — a tampered extension, rather than a careless click — while our Claude Haiku 5.5 pricing guide explains the model tier many developers pair with Claude Code.
The Bottom Line
"Don't ask again" is a small, polite button. It promises to stop interrupting you, and it keeps that promise — by writing the exact command you approved, secrets included, into a file inside your project. In most cases that file stays on your machine and nothing bad happens. In enough cases it did not stay on the machine: Apiiro found 1,122 public copies holding real secrets, and 2,539 secrets in total once history and transcripts were counted.
The lesson is not that Claude Code is unsafe, and it is not that you should go back to approving every command by hand. It is that a convenience feature which saves literal text will eventually save something you did not mean to share, unless you make a habit of keeping secrets out of commands in the first place.
So use the button — for safe, repeatable commands you have actually read. Write your standing permissions as wildcard patterns in the shared settings file. Deny reads of your secret files. And go and check your own repositories for `.claude/settings.local.json` today, before someone else finds it first. The ten minutes it takes are cheap. The database password sitting in a public repository is not.