If you use Claude Code and ever clicked "Yes, and don't ask again" on a command that contained a password or key, that secret may be sitting in a file in your project. Security firm Apiiro found real secrets in 1,122 public copies of .claude/settings.local.json on GitHub. Check your own repos first.

What to do

  1. Search your repos and your GitHub organization for .claude/settings.local.json and .claude/settings.json.
  2. Check git history for the file, even if it is gone from the current branch.
  3. Open each copy and read its allow list. Delete every rule that contains a secret.
  4. Untrack it: git rm --cached .claude/settings.local.json.
  5. Add .claude/settings.local.json to the repo's own .gitignore.
  6. Rotate every credential the file ever held. History, forks and clones keep old copies.

These steps are Apiiro's advice to developers.

How a secret ends up in the file

According to Apiiro's write-up, Claude proposes a shell command that carries a secret. You pick "Yes, and don't ask again". Claude Code then saves that exact command, secret included, as a permission rule in .claude/settings.local.json.

Anthropic's settings documentation says a "don't ask again" choice for a Bash command is saved as an allow rule in that file. Apiiro says this is Claude Code behavior, not the model's. It reproduced it with Opus 5.5 and Fable 5.1.

What Apiiro found

  • 104,185 public copies of the file, across 103,617 repos.
  • 1,122 of them (1.1%) hold a real secret: 1,379 distinct secrets, of which 636 are provider keys and 743 are passwords or tokens for public hosts.
  • Among them: 379 database passwords, 122 Supabase service-role keys, 23 AWS keys and 6 private keys.
  • Counting all sources, Apiiro found 2,539 real secrets in 1,994 public repos and 63 affected organizations. One organization confirmed its key had been live.
  • Earlier versions of the file hold 734 real secrets in 509 repos that are absent from the current copies.

Apiiro says it used read-only GitHub search on Nov. 1 to 3. It did not test any credential. A "real secret" means a match to a provider format or a pointer to a public host, not a confirmed valid one.

Why it ends up on GitHub

The docs say Claude Code adds **/.claude/settings.local.json to your global git excludes file the first time it writes the file in a git repo that does not already ignore it. They also say that if you create the file by hand, you must add it to .gitignore yourself.

Apiiro says the global ignore does not cover a folder that becomes a repo later, a clone on another machine, or a file already committed. The rule never goes into the repo's own .gitignore.

Apiiro also traced 1,105 repos with a real secret. In 539 of them, a commit co-authored by Claude changed the file.

What Anthropic said

Boris Cherny of the Claude Code team replied in the Hacker News thread on Nov. 7. He wrote: "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."

He also wrote that the file "is meant to stay local" and that "in this case the files were manually created and checked in." He added: "Permission rules are old hat. Everyone should be using auto mode instead," and "you should have secret scanning enabled."

In a follow-up he listed "making sure auto mode catches this, building in basic secret scanning, a few other ideas", to be prototyped "before we ship something."

Why scanners miss some

Gitleaks flagged 564 of the 1,122 files and TruffleHog flagged 643. Neither flagged 215, according to Apiiro. Those hold passwords inside commands, such as PGPASSWORD=, sshpass -p, mysql -p and bearer headers. Larger files are riskier: one in ten files over 8 KB holds a real secret, against fewer than one in 500 under 500 bytes.

Stop it happening again

  • Refer to secrets as variables. Apiiro says the saved rule then records $DB_URL, not the value.
  • Approve patterns such as Bash(npm run:*) instead of literal commands.
  • Turn on your host's secret scanning, as Cherny recommends.

Why it matters

A saved approval feels harmless, but it is a plain-text copy of your command. The ignore rule protects only the case the docs describe. A hand-made file, a clone or a repo created later needs its own .gitignore entry.

Apiiro says the median affected repo first committed the file 217 days before Nov. 2. Rotating a key is the only fix for one already pushed.

What we checked

We read Apiiro's write-up, Anthropic's settings documentation and the Hacker News comments quoted above, on Nov. 9. Ars Technica has also covered the findings. We did not run Apiiro's searches ourselves. The numbers are Apiiro's.

Related coverage: a tampered Claude Code extension in Cursor, Claude Code's refusal to clone existing games and 1Password for Agents. More under AI apps.