Guides

Claude Code saved your password in settings.local.json? Check and fix it

When Claude Code asks to run a shell command and you pick “Yes, and don’t ask again”, it saves that exact command to .claude/settings.local.json in your project. If the command had a password or an API key in it, the file now holds it in plain text. In November 2026 Apiiro found real secrets in 1,122 public copies of this file on GitHub. Here’s how it happens, how to check your own repos in five minutes, and what to do if something leaked.

How a password ends up in the file

You ask Claude Code to check why a login fails on staging, or to run a query against the database. It reads the connection details from your config and proposes a command that contains them, because the command can’t work without them. Claude Code asks before it runs a shell command. You choose “Yes, and don’t ask again”, and it saves the command as an allow rule, word for word:

.claude/settings.local.json

{
  "permissions": {
    "allow": [
      "Bash(PGPASSWORD=hunter2 psql -h db.example.com -U app -c 'select 1')"
    ]
  }
}

The password here is made up, but the shape is the real one. Claude Code keeps this file at the root of the git repository, even when you started it in a subfolder. The rule stays there until someone deletes it, long after the command ran. And the longer you’ve been clicking “don’t ask again” in a project, the more the file holds.

It’s easy to miss. Claude Code asks many times a session, and after the tenth prompt most of us stop reading the command. A password is one word in a long line.

What Apiiro found

Apiiro, an application security company, searched public GitHub on November 1–3, 2026:

Apiiro compared how 16 coding agents store approvals. Claude Code was the only one confirmed to write the full approved command to a project file by default.

“But Claude Code gitignores it”

It does, and that’s why most people think they’re safe. They aren’t always. The first time Claude Code writes the file in a git repository that doesn’t already ignore it, it adds **/.claude/settings.local.json to your global git excludes file on that machine (core.excludesFile, or ~/.config/git/ignore by default). Nothing goes into the repository’s own .gitignore, so the protection doesn’t travel with the project. It doesn’t cover:

Even a file that never leaves your Mac is plain JSON in the project folder, readable by any malware that scans developer machines for credentials.

Check your repos in five minutes

In each repository, from its root. The * also catches copies in subfolders, which Claude Code versions before 2.1.211 wrote to:

# Is the file tracked right now?
git ls-files '*settings.local.json'

# Was it ever committed, on any branch?
git log --all --oneline -- '*settings.local.json'

# Is it ignored, and by which rule?
git check-ignore -v .claude/settings.local.json

Then look inside every copy on your Mac for the patterns scanners miss:

# Every copy in your home folder
find ~ -path '*/.claude/settings.local.json' -not -path '*/Library/*' 2>/dev/null

# Rules that carry a password, a token or a key
grep -nE 'PGPASSWORD=|sshpass -p|mysql -p|Bearer |://[^ ]+:[^ ]+@|sk-|ghp_|AKIA' .claude/settings*.json

The grep is a filter, not a verdict: read each hit. You can also see and delete your allow rules inside Claude Code with /permissions. On GitHub, search your account or organization for path:.claude/settings.local.json, and do the same for .claude/settings.json. If you commit agent notes, memory files or chat transcripts, check those too: Apiiro found secrets in all three.

We ran this on the Mac we build Meowdoro on: four settings files, 54 allow rules, none that the grep flagged. Our repository also ignores the whole .claude/ folder in its own .gitignore, so even a bad rule wouldn’t get committed. That one line is the cheapest fix on this page.

If a secret leaked

  1. Rotate first. Revoke the key or change the password at the provider, today. Deleting the file doesn’t help: the secret stays in git history, and in every fork and clone. Apiiro found 734 secrets that were only in old versions of the file, and 211 forks carrying the same secrets.
  2. Untrack the file and ignore it in the repository itself:
    git rm --cached .claude/settings.local.json
    echo '.claude/settings.local.json' >> .gitignore
    git commit -m "Stop tracking Claude Code local settings"
  3. Delete the rule from your local copy too, or in /permissions. Otherwise the old password sits on your disk and gets used again.
  4. Clean the history if you need to, for example with git filter-repo --invert-paths --path .claude/settings.local.json and a force push. It’s worth doing on a public repo, but it doesn’t reach forks, so it never replaces rotation.
  5. Turn on secret scanning and push protection in your repository’s security settings, so the host warns you next time.

Stop it from happening again

What Anthropic says

Apiiro shared the research with Anthropic before publishing. On November 7 Boris Cherny, who leads Claude Code, answered on Hacker News that the team is “looking into what we can do to prevent this.” The ideas he named: making auto mode catch it and building in basic secret scanning, to be prototyped before anything ships. He also said Claude Code gitignores the file when it creates it, so in his view the exposed copies were made by hand and checked in, and he recommended auto mode and the secret scanning that GitHub and other hosts offer. Until a fix ships, the checks above are on you.

Where Meowdoro fits

We built Meowdoro, a focus timer around the MacBook notch that shows your Claude Code and Codex sessions. It never approves anything and never reads your commands. It shows which session is waiting for a permission, so you can answer it when you’re back at the desk and able to read the line, instead of clicking “don’t ask again” in between two other things. Try it and tell us what’s missing.

Questions

What is .claude/settings.local.json?

Your personal Claude Code settings for one project. Claude Code applies it over the shared .claude/settings.json and writes your standing approvals into it, such as “Yes, and don’t ask again” for a Bash command. It’s meant to stay on your machine.

Does Claude Code add settings.local.json to .gitignore?

It adds it to your global git excludes file the first time it writes the file in a repository that doesn’t already ignore it. It doesn’t touch the repository’s own .gitignore, and it doesn’t cover a file you made by hand or one that’s already committed. Add the line to the repository’s .gitignore yourself.

Is the file safe if I never committed it?

Safer, not safe. It’s plain text in your project folder, so malware or a copied folder can take it. Delete any rule with a secret in it, even if the file never left your Mac.

Does deleting the file fix a leak?

No. The secret stays in git history, forks and clones. Rotate the credential first, then untrack and ignore the file.

Does this happen in Codex?

Apiiro compared 16 coding agents’ documentation and found only Claude Code confirmed to write the full approved command to a project file by default. Any agent can still leak a secret you type into a command into its transcripts or notes, so the same habits help everywhere.

Numbers: Apiiro, “Coding Agents Are Leaking Your Secrets to GitHub”, with its November 8 update quoting Boris Cherny, read on November 9, 2026. How the file works: the Claude Code documentation on settings and permissions, read on November 9, 2026. The example password is made up.