Claude Code stores passwords or tokens in plain text in .claude/settings.local.json for any command you approve with “Yes, and don’t ask again”. If that file ends up in a public repo, anyone can read it: Apiiro Research reviewed 104,185 public copies of the file on GitHub and found a real secret in 1,122 of them, just over 1 percent. Adding git history, shared configuration files, and agent transcripts, the total reaches 2,539 distinct secrets in 1,994 repos.
Status as of November 8, 2026: Anthropic has not published a fix or indicated which version it will arrive in. The study figures come from a snapshot of default branches taken on November 2, 2026.
The study, by Shmulik Cohen and Matan Giladi, was published on November 5, 2026. The checks in this note take a few minutes per repo and don’t depend on Apiiro’s figures being exact.
Does Claude Code store my passwords in settings.local.json?
Yes, through the approval prompt. Ask Claude Code to review why login is failing on staging or to run a migration, and the command it proposes carries whatever credential is in your configuration: a connection string, a PGPASSWORD=, an sshpass -p, or a bearer header. Without it, the command doesn’t work.
Claude Code asks before executing a shell command. If you choose “Yes, and don’t ask again”, according to Anthropic’s own documentation, it stores that approval as an allow rule in .claude/settings.local.json, at the root of your git repository. The rule is the command exactly as it appears in the option you chose. When that option shows the complete command line, the secret it contains enters the file with it.
Apiiro says this is Claude Code’s behavior, not the model’s: they reproduced it with Opus 5.5 and Fable 5.1. And the longer you spend approving with “don’t ask again”, the worse: one in ten files larger than 8 KB held a real secret, compared to fewer than one in 500 among those smaller than 500 bytes.
This is what Apiiro found, by type:
| Type | Count |
|---|---|
| Database passwords | 379 |
| Supabase service-role keys | 122 |
| Supabase account tokens (control all account projects) | 103 |
SSH access, some as root with sshpass |
43 |
| GitHub, GitLab, and npm tokens | 42 |
| AWS keys | 23 |
| Private keys | 6 |
That’s 1,379 distinct secrets just in current copies of settings.local.json. There are 63 affected organizations, from student groups to startups, agencies, and established vendors. Cases include: a Postgres production password on Azure, a Square production token, and the database owner password for a clinical records app.
How do I know if Claude Code leaked my secrets to GitHub?
With four checks, following Apiiro’s procedure. Replace your-org with your GitHub organization or username.
1. Is the file public right now?
Search for the file in your organization’s code on GitHub:
path:.claude/settings.local.json org:your-org
For a personal account, use user:your-username instead of org:. Repeat the search with path:.claude/settings.json: this is the shared configuration file that teams intentionally upload, and Apiiro found real secrets in 298 of the 76,011 public copies it reviewed. Code search shows files as they are today; history is step 3.
2. Is Git tracking the file in this repo?
From inside each repo:
git ls-files .claude/settings.local.json
If it prints the path, git is tracking the file and every push publishes it.
3. Was it ever pushed to git history?
git log --all --oneline -- .claude/settings.local.json
Any output means the file is in history, even if it doesn’t exist in your working directory today. To see what each version contained, add -p:
git log --all -p -- .claude/settings.local.json
This matters more than it seems. Apiiro found 734 secrets that only exist in earlier versions of the file, in 509 repos, almost always because someone deleted the file and considered the problem solved. Also, 211 forks of 74 repos have the same secrets.
4. What do your local copies contain?
Most of these files never reach GitHub, but they’re still a plaintext JSON credential store on your laptop. Find all copies:
find ~ -path '*/.claude/settings.local.json'
Search everywhere, not just at repo roots: before version 2.1.211, Claude Code saved the file in the directory you started it from, so there may be old copies in subdirectories. Open each one and read its allow list: each entry is a command you approved, with everything you wrote in it. Inside Claude Code, /permissions also shows all rules and which file each comes from.
I found a secret: how do I rotate it and remove it from git with git rm --cached?
Rotate first, then clean. Deleting the file doesn’t clean git history, forks, or clones, so the credential has to be considered burned.
- Rotate all credentials the file ever had, including those that only appear in old commits from step 3.
- Stop tracking the file and keep it out forever:
Then addgit rm --cached .claude/settings.local.json.claude/settings.local.jsonto the repo’s own.gitignore. - Delete all rules containing a secret, also in files never uploaded.
- Stop writing secrets inside commands. Refer to them as environment variables from your secrets manager, so the rule saves
$DB_URLinstead of the password. - Approve patterns, not literal commands. A rule like
Bash(npm run *)covers all npm scripts and doesn’t save arguments. Anthropic’s documentation also accepts the earlier formBash(npm run:*)as equivalent; the permissions dialog writes the form with a space.
Doesn’t Claude Code already exclude this file from git?
It tries, and there’s the gap. According to Anthropic’s settings documentation, the first time Claude Code writes .claude/settings.local.json inside a git repo, it adds **/.claude/settings.local.json to your global git exclusions file. That covers the common case on your machine.
It doesn’t cover:
- a folder that becomes a repo after the file was created;
- a clone on another machine or a teammate’s laptop;
- a file someone already uploaded;
- a file you created by hand: the documentation asks you to add it to
.gitignoreyourself.
Since the exclusion lives in your global git configuration and not in the repo’s .gitignore, nothing travels with the project to protect it.
The two sides read the evidence differently. Boris Cherny, who leads Claude Code, wrote on Hacker News that in these cases the files were created by hand and uploaded by hand. Apiiro reports that in 539 of the 1,105 repos with a real secret it tracked, a commit co-authored by Claude modified the file, with models from Sonnet 4.5 to Opus 5.5. Both things can be partially true; in either case, your fix is the same.
Why didn’t gitleaks and TruffleHog detect these passwords?
Because the secrets leaked here almost never have key format. Apiiro ran gitleaks and TruffleHog on all 104,185 files. Of the 1,122 that held a real secret, gitleaks flagged 564 and TruffleHog 643; 215 neither detected.
Secret scanners search for key formats: a provider prefix, a long random string. A password after PGPASSWORD=, sshpass -p, or mysql -p, or inside a bearer header in a curl, is any word in any command line. The same pattern appears everywhere an agent logs what it ran: transcripts, memory files, handoff notes.
That gap matters on your laptop too. In September 2025, the npm worm Shai-Hulud downloaded TruffleHog and ran it on its victims’ files: the same scanner that already detects 643 of these files.
What should security teams change?
These are Apiiro’s recommendations for teams, and they apply to any programming agent, not just Claude Code:
- Treat agent folders as secret-bearing, just like
.env:.claude/,.cursor/,.gemini/,.specstory/, and agent memory files, both on laptops and in repos. - Include them in pre-commit and CI secret scanning, with history included, and check that your scanner detects passwords inside commands (
PGPASSWORD=,sshpass -p,mysql -p, bearer headers), not just provider key formats. - Add
.claude/settings.local.jsonto your organization’s.gitignoretemplates. - Prioritize credentials that come with a public host: those are what give access.
Apiiro also found the same habit in other agents’ files: real secrets in 120 agent chat transcripts in 87 repos (exports from .specstory, aider, and Cursor) and in Copilot’s auto-approve settings in VS Code in 9 repos. But according to its reading of each one’s documentation, Claude Code is the only one of 16 programming agents that by default writes the complete approved command to a project file.
What has Anthropic said?
Apiiro shared the research with Anthropic before publishing. In his Hacker News comment, Cherny said Claude Code hasn’t historically scrubbed secrets from these rules and the team is looking at how to prevent it; Apiiro adds that basic secret scanning is one of the approaches Anthropic will prototype. Cherny also recommended two things:
- Auto mode instead of permission rules. In auto mode, a background classifier reviews actions before they run, so you don’t accumulate an
allowlist. According to Anthropic’s documentation,defaultModeset toautoonly takes effect from your user configuration (~/.claude/settings.json) or from managed configuration, not from project or local config. - Secret scanning on your code control platform, whichever agent you use.
At the time this note was published, Anthropic had not released any fix or indicated a version. Users have reported this mechanism in GitHub issues since August 2025 (#5544, #11982, #13106, #91270); according to Apiiro, none received a response from Anthropic and three were automatically closed for inactivity or as duplicates.
How reliable are Apiiro’s numbers?
Solid on the mechanism, which Anthropic’s own documentation confirms, with limits worth knowing:
- Apiiro sells secret security and ASPM products, so it has a commercial interest in the finding.
- “Real secret” doesn’t mean validated. No credential was tested and no host was contacted. It means a value that matches a provider format or that sits next to a public host. Only one organization confirmed their key was active.
- Classification combined rules with an independent LLM reviewer that worked from a written rubric; a value counted only when both matched.
- The history figure is a floor, and gitleaks and TruffleHog were run without their verification modes.
- The comparison of 16 agents comes from reading documentation, not testing.
- The figures are a snapshot of default branches from November 2, 2026. Organizations are described by sector, not by name: it’s responsible, but means no case can be independently verified.
Prior work points the same way: ironPeak found the file in its own repo in February 2026, and Lakera found credentials in 33 of these files within 30 npm packages in April.
What is Claude Code?
Claude Code is Anthropic’s agentic coding tool: it works in the terminal, in IDEs, and in Claude’s desktop app, reads your repo, edits files, and runs shell commands on your behalf, asking for approval unless a rule or mode says otherwise. That approval system is what generates settings.local.json, and it’s why a command the agent writes can carry—and permanently record—any credential it saw.
What about you? What’s the first thing you check when you clone a repo that has a .claude/ folder?
- With “Yes, and don’t ask again” most of the time
- I write my own rules with patterns
- I use auto mode
- I prefer another option (tell us which)
Comment below or, if this article reached you by email, reply directly to the email: your reply gets published here.
