← All Articles 🔑 Secret Detection Critical By Nishant Kumar Verma

Claude Code "Don't Ask Again" Leak: Secrets in settings.local.json

Apiiro found 2,539 secrets in public repos, many saved by Claude Code's "don't ask again" in .claude/settings.local.json. How to check, rotate and untrack it.

SEC-014 PRJ-001

Quick Answer

When you pick "Yes, and don't ask again" in Claude Code, it saves the exact command as an allow rule in .claude/settings.local.json, including any password typed into it. Apiiro found 1,122 public copies of that file on GitHub holding a real secret, and 2,539 distinct secrets in 1,994 repositories once git history, shared settings and agent transcripts were counted. Check whether the file is tracked in your repo, rotate anything it ever held, then untrack it.

What Apiiro Found

The research, published by Apiiro and collected from read-only GitHub searches on 1 to 3 November 2026, counted 104,185 public copies of .claude/settings.local.json in 103,617 repositories. 1,122 of them (1.1%) held a real secret, 1,379 distinct secrets in total.

What was in the files Count
Database passwords379
Supabase service-role keys122
Supabase account tokens (control every project in the account)103
SSH logins, some with a root password in an sshpass command43
GitHub, GitLab and npm tokens42
AWS keys23
Private keys6

Deleting the file did not end the exposure. Earlier versions in git history held 734 secrets that appear in no current copy, and 211 forks of 74 repositories carried the same secrets. In the median affected repo, the file had been on the default branch for 217 days. Sixty-three organizations were affected, from student groups to software agencies and established vendors, and one confirmed its key had been live.

Apiiro says it tested no credential and contacted no host. "Real secret" means a value in a known provider format, or a password next to a public host, not one proven to work.

How a Password Ends Up in the File

Claude Code asks before it runs a shell command. The Claude Code settings docs say that after "Yes, and don't ask again", the approval is saved as an allow rule in .claude/settings.local.json. The rule is the command itself. If the command was PGPASSWORD=... psql -h your-db-host, the password is now in a JSON file inside your project folder.

Claude Code does try to keep that file private. The docs say that when it first writes the file, it adds **/.claude/settings.local.json to your global git excludes. Apiiro points out what that does not cover:

  • a folder that only becomes a git repo later,
  • a clone of the project on another machine,
  • a file that was already committed, which git keeps tracking whatever the ignore rules say.

The rule lives in your machine's settings, not in the project's own .gitignore, so nothing travels with the repo. Apiiro also traced 1,105 repos with a real secret and found that in 539 of them, a commit co-authored by Claude had changed the file.

The same habit shows up in other agent files. Apiiro found secrets in 298 shared .claude/settings.json files, which teams commit on purpose, and in saved agent transcripts and memory files. We covered a different risk in the same folder in Claude Code settings as an attack surface.

Why Secret Scanners Miss Half of These

Apiiro ran Gitleaks and TruffleHog over all 104,185 files. Of the 1,122 files with a real secret, Gitleaks flagged 564 and TruffleHog 643, and 215 were flagged by neither.

The reason is the shape of the secret. Scanners look for key formats: a provider prefix such as ghp_ or a long random string. A password typed after PGPASSWORD=, sshpass -p or mysql -p is an ordinary word in an ordinary command line.

We reproduced this with Gitleaks 8.30.1. A GitHub token inside an allow rule in .claude/settings.local.json was flagged as github-pat. A database password after PGPASSWORD= in the same file produced no finding. A clean scan of this file is not proof it is clean.

Check If You Are Affected

Run these in each repository where you use Claude Code (on Windows, use Git Bash):

# 1. Is the file tracked right now? Any output means yes.
git ls-files .claude/settings.local.json .claude/settings.json

# 2. Was it ever committed, even if it is gone today?
git log --all --oneline -- .claude/settings.local.json

# 3. Look for passwords typed into approved commands
grep -nE "PGPASSWORD=|sshpass -p|mysql -p|Bearer |://[^\"/ ]+:[^\"@ ]+@" .claude/settings.local.json

If step 2 prints commits, the file is in your history, and in every fork and clone made since. Also search your GitHub organization with the code search query path:.claude/settings.local.json org:YOUR-ORG: each hit in a public repo is a file anyone can read.

How to Fix It

Rotate first, clean up second. A secret that reached a public repo has to be treated as known, and removing the file does not remove it from history, forks or clones.

  1. Rotate every credential the file ever held. Change the database password, revoke the token, issue a new key. See secrets in git history for why history rewrites come after rotation, not instead of it.
  2. Untrack the file and ignore it in the repo itself:
    git rm --cached .claude/settings.local.json
    echo ".claude/settings.local.json" >> .gitignore
    git commit -m "Stop tracking Claude Code local settings"
    git push
  3. Open .claude/settings.local.json and delete every rule that contains a secret, even if the file was never committed. It is still plain text on your laptop.
  4. Stop typing secrets into commands. Keep them in environment variables or your secrets manager and reference them, so the saved rule holds $DATABASE_URL, not the password.
  5. Approve patterns, not one-off commands. A rule like Bash(npm run test:*) covers a task without recording what was typed into it.
// Bad: the approved command, password and host included
{
  "permissions": {
    "allow": [
      "Bash(PGPASSWORD=Tr4inStation92 psql -h db.prod-example.com -U postgres)"
    ]
  }
}
// Fixed: patterns for scripts that read secrets from the environment
{
  "permissions": {
    "allow": [
      "Bash(npm run test:*)",
      "Bash(npm run db:check)"
    ]
  }
}

VibeDoctor's Vibe Check runs Gitleaks over every file in your repository, including the .claude folder, and flags a committed .env that holds a real key, with file paths and line numbers. As the test above shows, Gitleaks will not catch a plain password inside a command, so run the grep check too. Free to sign up.

What Anthropic Said

Apiiro says it shared the research with Anthropic before publishing and reported each organization case to its owner on 2 and 3 November. According to Apiiro's update, Boris Cherny, Anthropic's head of Claude Code, replied on Hacker News on 7 November that the team is "looking into what we can do to prevent this". He named options it plans to prototype, including making auto mode catch it and building in basic secret scanning.

He also said Claude Code gitignores the file when it creates it, so in his view the exposed copies were created by hand and checked in. He recommended auto mode over permission rules, and turning on the secret scanning that GitHub and other hosts offer. Until a fix ships, the steps above are on you.

FAQ

Is .claude/settings.local.json ignored by git automatically?

Claude Code's docs say it adds the file to your global git excludes when it creates it. That covers only your machine, not other clones, a folder that becomes a repo later, or a file already committed. Add it to the repo's own .gitignore too.

Is "don't ask again" a bug in the model?

No. Apiiro says the behaviour is in Claude Code itself, not the model, and it reproduced it with current models. The tool saves the approved command string as the rule.

I deleted the file. Am I safe?

No. Apiiro found 734 secrets that exist only in earlier versions of the file. If it was ever committed, rotate the credentials, because history, forks and clones still have them.

Does my secret scanner catch this?

Partly. In Apiiro's test Gitleaks flagged 564 of 1,122 files with a real secret and TruffleHog 643. Passwords inside commands, such as after PGPASSWORD=, are what both tools mostly miss.

Does this only affect Claude Code?

Apiiro compared 16 coding agents and found Claude Code is the only one confirmed to write the full approved command to a project file by default. It also found secrets in other agents' transcripts and in VS Code Copilot auto-approve settings.

Diagnose your codebase - free

VibeDoctor checks for SEC-014, PRJ-001 and 148 other issues across 21 diagnostic areas - security, performance, code quality, and more.

SCAN MY APP →