What did Apiiro find in public GitHub repositories?
Apiiro, an application security vendor, published the research on 5 November 2026. The authors, Shmulik Cohen and Matan Giladi, searched public GitHub for one file: .claude/settings.local.json. Between 1 and 3 November they found 104,185 copies of that file in 103,617 repositories.
Of those copies, 1,122 held at least one real secret, about 1.1% of the files scanned. Apiiro counted 1,379 distinct secrets on default branches: 636 provider keys and 743 passwords or tokens for public hosts.
The single-file count understates the exposure. Apiiro also checked git history, the shared .claude/settings.json that teams commit on purpose, and saved agent transcripts. Those sources added 1,160 more secrets and raised the total to 2,539 across 1,994 repositories.
Large allow lists carry more risk, according to Apiiro. One in ten files larger than 8 KB held a real secret, against fewer than one in 500 files under 500 bytes. A long allow list means a developer approved many commands, and each approval could carry a credential.
In total, 63 organisations held a real secret in a public allowlist. Apiiro described the most serious cases without naming them. They include a database vendor's own cloud key with management access, a startup's production Azure Postgres password, a software agency's Square production token and the owner password for a medical-records database.
The definition of a real secret was deliberately narrow. A value counted when it matched a known provider format, or when a password or token sat next to a public host. Apiiro filtered dummy values, default passwords and keys that are public by design, then had an independent model review every candidate in masked context.
Apiiro did not use or test any credential, and it did not contact any host. So the count shows exposure, not confirmed working access. One affected organisation confirmed to Apiiro that its exposed key had been live. The largest groups were credentials that open a database directly:
- •379 database passwords
- •122 Supabase service-role keys
- •103 Supabase account tokens
- •43 SSH logins, some for public servers
- •42 GitHub, GitLab and npm tokens
- •23 AWS keys and 6 private keys
How does 'don't ask again' put a password in a settings file?
Claude Code asks for permission before running most shell commands. A long session can produce many prompts, and the tool offers a shortcut: Yes, and don't ask again. That option exists to reduce approval fatigue, which is a real problem for agentic coding.
The shortcut saves a permission rule to the project's local settings file. The rule stores the command text that was approved, not just the name of the program. If the developer typed a password or token into that command, the secret is stored with it.
"Pick 'Yes, and don't ask again' and it saves that exact command, secret included, to .claude/settings.local.json inside the project folder," Apiiro's report says.
The file belongs inside the project, but it is meant to stay on one machine. When Claude Code creates it inside a git repository, it adds the path to the developer's global git ignore list. That covers the common case without requiring setup.
That protection has three gaps, according to Apiiro. It does not cover a folder that becomes a repository later, a clone on another machine, or a file that someone has already committed. The rule never enters the repository's own .gitignore, so nothing in the project blocks a commit.
Git makes the remaining gap worse. Claude Code's documentation says a settings.local.json that git tracks is treated as repository-supplied settings. Apiiro quoted a debug log line: "is tracked in the index; gitignore rules do not apply to tracked files." The user is not warned, and the next approval is appended to the tracked file.
These files have been public for a while. In the median affected repository, the file was first committed 217 days before 2 November 2026. In 118 repositories, it arrived more than a year earlier.
The behaviour belongs to the tool rather than any one model. Apiiro says it happens with Anthropic's latest models, and it reproduced the file write with Opus 5.5 and Fable 5.1.
Why did gitleaks and TruffleHog miss 215 of the files?
Apiiro ran two widely used open-source scanners over all 104,185 files. Gitleaks flagged 564 of the 1,122 files that held a real secret. TruffleHog flagged 643. Neither tool flagged 215 of them.
The misses follow a pattern. Both scanners look for key formats, such as a provider prefix followed by a long random string. A password typed after PGPASSWORD=, sshpass -p or mysql -p reads as an ordinary word in an ordinary command line.
That blind spot is not limited to one filename. Agent chat transcripts, memory files and handoff notes repeat commands, so a scanner tuned to key formats misses the same passwords wherever the agent recorded them.
Apiiro also looked outside GitHub. Of 31,053 public Hugging Face Spaces, 126 held .claude/settings.local.json, and one contained a database service key plus a user password. On GitLab.com, 2 of 69 public copies held a real secret, including a GitLab access token.
The scale of the other files is smaller, but the mechanism is identical. Each one records what a developer approved, and none is treated as a secret file by default.
The scanner gap has a practical consequence. A team that relies only on GitHub's default secret scanning can see a clean dashboard while a database password sits in a plain JSON file in the same repository. Apiiro's counts for the other agent-written files were:
- •Shared .claude/settings.json: 298 of 76,011 files held a real secret
- •Agent chat transcripts: 120 files in 87 repositories, from 2,523 checked
- •Agent memory files: 9 repositories, from 1,200 files checked
- •Handoff and deploy notes: 33 files, a third of them written by the agent
- •VS Code Copilot auto-approve settings: 9 repositories, from 173 checked
What has Anthropic said about the leak?
Apiiro shared the research with Anthropic before publication and notified affected organisations on 2 and 3 November. The company's most detailed public response came from Boris Cherny, who leads Claude Code, in a Hacker News thread on 7 November.
"Historically Claude Code has not done secret scrubbing ... but we are looking into what we can do to prevent this," Cherny wrote. He said the team would prototype a few options and study the trade-offs before shipping.
His list of approaches was specific: "making sure auto mode catches this, building in basic secret scanning, a few other ideas." Auto mode is the permission model Anthropic now recommends, and Cherny says it is enabled by default and included in every plan.
Cherny also disputed part of the framing. He said the file is meant to stay local, and that Claude Code gitignores it when the tool creates it. In his view, the exposed copies were created manually and checked in. He recommended auto mode over permission rules and asked users to enable the secret scanning that GitHub and other hosts provide.
A reader pointed out that auto mode can also ask about a sensitive command, which means the same secret could be saved through a different path. Cherny replied: "Yeah good catch. Thinking through what we can do to improve this (ideas welcome)."
Apiiro's data complicates the manual-commit explanation. In 539 of the 1,105 repositories it traced, a commit co-authored by Claude changed the secret-bearing file. Those commits name models from Sonnet 4.5 to Opus 5.5.
Apiiro also says Claude Code's commit instructions tell the model not to commit .env or credentials.json. The list does not include the agent's own settings file, which leaves the default path unguarded.
Users had reported the mechanism earlier. Apiiro links four issues in Anthropic's claude-code repository, reported since August 2025. One of them, issue 13106, describes tokens stored in the local settings file and not ignored by default. GitHub shows that issue opened on 4 December 2025 and now closed.
Apiiro says none of the four received a reply from Anthropic and that three were closed automatically as inactive or duplicate. The report's 8 November update lists the Hacker News thread as the company's response.
Who is affected, and how serious is the exposure?
The 63 organisations range from student and hackathon groups to startups, software agencies, IT services firms and established vendors. Some were exposed through their own demo and workshop repositories, which are often public by design.
The secrets are not confined to current files. Apiiro found 734 real secrets in earlier versions of the file, across 509 repositories, that no current copy contains. Deleting a file does not remove it from git history, forks or clones.
Forks carry copies as well. Apiiro found 211 forks of 74 repositories holding the same secrets. A leaked Supabase service-role key carries elevated access to a project, while a Supabase account token controls every project on the account. Some of the exposed SSH logins were root passwords.
Local machines are exposed too. The allowlist is plain JSON in the project folder, and it can leave through a published npm package, a Docker image, an archive or a synced folder. It can also stay there until someone reads it.
Malware already targets this class of file. In September 2025, the Shai-Hulud npm worm downloaded TruffleHog and ran it over victims' files to harvest credentials. That scanner catches 643 of the 1,122 files, so it would find most of them.
Apiiro also notes that malicious Nx packages had told developers' own Claude Code and Gemini CLI installations to search the disk for secrets. An agent with broad filesystem access is a useful tool for an attacker.
The limits of the research matter for anyone assessing their own risk. Apiiro did not test whether the credentials still work, so some may have been rotated or revoked. Its counts are a floor, because code search caps results and the other files were sampled by key pattern.
The history review covered 43,120 repositories, including every repository whose commits mention removing, untracking, redacting or rotating the file. That makes the 734 old secrets a minimum rather than a full count.
What should developers and security teams do now?
Apiiro's advice is to rotate first and clean up second. Deleting the file does not clear history, forks or clones, so every credential the file has ever held should be replaced. Then the file can be cleaned up.
A quick check has three steps. First, search your organisation's repositories for .claude/settings.local.json and .claude/settings.json. Second, check each repository's history for the file, even if it is gone today. Third, open local copies and read the allow list for passwords, tokens, keys and connection strings.
If the file is tracked, untrack it with git rm --cached .claude/settings.local.json and add it to the repository's own .gitignore. Organisations should also add the path to their gitignore templates, so new projects start protected.
The durable fix is to stop typing secrets into commands. Reference a variable such as $DB_URL, so the saved rule records the variable name rather than the value. Approve patterns such as Bash(npm run:*) instead of exact command strings.
Security teams should treat agent folders as secret-bearing, the way they treat .env. That includes .claude/, .cursor/, .gemini/ and .specstory/, plus memory files and handoff notes. These paths belong in pre-commit hooks and CI scanners, including scans of history.
Scanner rules need to catch passwords inside commands, not only provider key formats. Apiiro suggests looking for PGPASSWORD=, sshpass -p, mysql -p and bearer headers in curl calls. Generic tools will not catch those on their own.
Credentials paired with a public host deserve attention first, because they grant access rather than disclose a value. A database password and a Supabase service-role key are more urgent than a random personal access token with narrow scope.
What happens next for Claude Code and other coding agents?
Anthropic has not published a timeline or a commit to a specific fix. Cherny said the team would prototype approaches, which leaves open whether Claude Code gains built-in secret scanning, changes how it stores approvals, or both.
The commit instructions are one thing to watch. If the model's guidance covered .claude/settings.local.json, the co-authored commits that Apiiro traced would become less likely. A small documentation change could remove a large share of new exposures.
The wider agent market matters too. Apiiro compared how 16 coding agents store approvals from their documentation. It found Claude Code was the only one confirmed to write the full approved command to a project file by default.
Git hosts are another control point. GitHub's secret scanning and push protection can block known key formats, but a password inside a shell command often escapes them. Organisation-level push protection only helps if the pattern is recognised.
For users, the practical lesson is that approval fatigue is a security control problem, not just a usability one. Apiiro argues that after enough prompts, most people stop reading the command, and the one that contains a credential looks like the others.
The story is also a reminder that agents change the threat model for local configuration. Files that once held preferences now hold command history, and command history now holds whatever a developer typed to make a task work.
