AI news, with the context that matters.

Products & Services · ·

Claude Code's "Don't ask again" and secrets in public repositories: inside 1,122 files, and the 19% two scanners missed

Security firm Apiiro examined 104,185 Claude Code settings files on public GitHub and found 1,379 secrets in 1,122 of them. Choosing "Don't ask again" at an approval prompt saves the command, password included, as a permission rule. We checked the mechanism against the original report, Claude Code's documentation and changelog, and GitHub issues, and calculated the kinds of secrets, how the share rises with file size, what the scanners missed and how many secrets remain in history. We also include steps to check your own repositories.

Ask Claude Code to check what is in a database, and it may propose a psql command that includes the connection password. Choose "Yes, and don't ask again" at the approval prompt, and Claude Code runs the command and writes the command string to .claude/settings.local.json as a permission rule. The password stays there in plain text, inside the project folder.

On November 5, security firm Apiiro published a report on these files in public GitHub repositories. Of 104,185 files, 1,122 contained 1,379 secrets, such as passwords and API keys. A figure of 2,539 also spread in the coverage, but that number combines other files and history. This article separates what each number counts and calculates the kinds of secrets, how the share relates to file size, what detection tools missed and how many secrets remain in history. At the end, it lists steps for checking your own repositories.

We checked the figures on November 8 against Apiiro's original report (published November 5, updated November 8), Claude Code's official documentation and changelog, and GitHub issues. Apiiro did not test any of the credentials it found. Its "real secrets" were judged by format and pairing with a public host, not confirmed as valid. The ratios are LATENT's calculations. This article does not cover how to find secrets in other people's repositories.

Apiiro report / Claude Code settings documentation / Claude Code permissions documentation

Key takeaways

  1. Apiiro examined 104,185 .claude/settings.local.json files on public GitHub and found 1,379 secrets in 1,122 of them (1.08%). Of those secrets, 36.3% were passwords or keys that open a database directly. Files over 8KB are 2.6% of all files but 24.3% of the files containing secrets. The more approvals a file accumulates, the more likely it holds a secret.
  2. The scanner gitleaks detected 50.3% of the 1,122 files and TruffleHog 57.3%. Even used together, they missed 215 files, or 19.2%. Passwords written inside commands are hard for scanners that look for key formats to catch.
  3. The first time Claude Code writes this file, it registers it in that machine's git exclude settings. That registration does nothing on another machine or container, in a copied folder, or for a file already tracked. In 48.8% of repositories with secrets, a commit recording Claude as co-author had changed this file. Another 734 secrets survive only in past commits, so rotating keys comes first.

How Apiiro counted, and what each number means

The report's authors are Shmulik Cohen and Matan Giladi of Apiiro. From November 1 to 3, 2026, Apiiro read the default branches of public repositories using GitHub's code search and commit search. It collected all 104,185 .claude/settings.local.json files (in 103,617 repositories) and all 76,011 shared .claude/settings.json files. It also examined file history in 43,120 repositories.

Secrets were counted in two kinds. One is keys matching a provider's format, such as OpenAI, Anthropic, AWS, GitHub and Supabase. The other is passwords and tokens with no fixed format, counted only when a public host appears on the same line. Placeholders, common default passwords, local hosts and keys meant to be public were excluded. Apiiro also had an LLM reviewer judge the remaining 2,774 distinct values in redacted form, and counted only values that both the rules and the reviewer judged real. Apiiro writes that it shared the research with Anthropic before publication and contacted affected organizations on November 2 and 3.

The numbers in the coverage each count something different. Table 1 sorts them out.

Number What it counts
104,185 .claude/settings.local.json files on public GitHub
1,122 Of those, files containing at least one real secret (1.08%)
1,379 Distinct secrets in those 1,122 files
734 Secrets found only in past commits of the file, not in any current file (509 repositories)
1,160 Additional secrets found in history, shared settings files and chat transcripts
2,539 Distinct secrets across everything examined (1,994 repositories)

Subtracting 1,379 from 2,539 gives 1,160, matching the report. Subtracting the 734 from history leaves 426, which appears to be the shared settings files and chat transcripts, though the breakdown is not published. That works out to 1.23 secrets per file on average.

Apiiro report

How approved commands end up in a settings file

According to Claude Code's permissions documentation, choosing "Yes, and don't ask again" when approving a Bash command makes the approval permanent per repository and command. It is saved as a permissions.allow rule in .claude/settings.local.json at the repository root. The prompt shows the form of the rule to be saved, as in "Yes, and don't ask again for: npm test *". For a command joined with &&, up to five rules can be saved, one for each part that needs approval.

File-edit approvals last only until the session ends. Approvals that persist are those for Bash commands, WebFetch domains and web search.

A figure in Apiiro's report shows the shapes of the leaked rules: a psql command passing a password through an environment variable, an ssh command passing a password to sshpass with -p, a curl command with a token in the Authorization header, and a psql command whose connection string includes a username and password. Its example of a safe rule takes arguments with *, as in npm run, and contains no secret.

Apiiro reproduced the behavior with Opus 5.5 and Fable 5.1 and concluded that it is Claude Code's behavior, not the model's. It also compared the documentation of 16 coding agents and writes that Claude Code was the only one it could confirm writes the full text of approved commands to a project file by default. The report does not name the 16 tools or include the comparison table.

Where the rule is saved depends on where you use Claude Code. According to the settings documentation, the CLI writes only to your own .claude/settings.local.json. In the VS Code extension, the approval prompt lets you pick the destination file, including the team's shared .claude/settings.json. Issues #77530 in July 2026 and #91270 in September reported approvals in the VS Code extension being written to the shared settings file.

Claude Code permissions documentation / Claude Code settings documentation / Issue #77530 / Issue #91270

When the git exclude registration does not help

According to the settings documentation, the first time Claude Code writes this file in a git repository, it adds **/.claude/settings.local.json to the global git excludes file. That file is the path set in core.excludesFile, or ~/.config/git/ignore if none is set. The registration keeps the file out of commits in every repository on that machine. A file you create by hand is not covered, and the documentation says to add it to .gitignore yourself.

The registration goes into that machine's settings, not the repository's .gitignore. On Hacker News, Apiiro's author listed three cases where it does not help: a new machine or container without the global exclude, a copied project folder, and a file that has already been committed. Git does not apply exclude rules to tracked files, so once committed, later changes to the file are recorded too. Apiiro's report also lists folders that became git repositories later.

Claude Code's changelog contains related fixes. Version 2.1.307 fixed self-hosted runner sessions committing a .claude/settings.local.json left by an earlier session. Version 2.1.271 made the VS Code extension's hooks dialog register the file as ignored before the save returns. Among GitHub issues, #11982 from November 2025 reported that creating the file in 2.0.46 did not add it to the excludes.

Of the 1,105 repositories with secrets that Apiiro tracked, 539 (48.8%) had a commit recording Claude as co-author that changed this file. The models recorded ranged from Sonnet 4.5 to Opus 5.5.

Claude Code settings documentation / Claude Code changelog / Apiiro author's comment on Hacker News / Issue #11982

The kinds of the 1,379 secrets

Table 2 breaks down the 1,379 secrets. There are 636 keys in provider formats and 743 passwords or tokens used with public hosts.

Kind Count
Service API tokens 398
Database passwords 379
AI model API keys 149
Supabase service-role keys 122
Google API keys 110
Supabase account tokens 103
SSH logins to public servers 43
GitHub, GitLab and npm tokens 42
AWS keys 23
App and account passwords 9
Private keys 6
Horizontal bar chart of secrets by kind: service API tokens 398, database passwords 379, AI model API keys 149, Supabase service-role keys 122, Google API keys 110, Supabase account tokens 103, SSH logins 43, GitHub, GitLab and npm tokens 42, AWS keys 23, app passwords 9, private keys 6. 501 open a database directly
Figure 1. Kinds of secrets in public .claude/settings.local.json files. Source: figure in Apiiro's report

Database passwords and Supabase service-role keys together, 501 secrets, open a database directly. That is 36.3% of the 1,379. Supabase account tokens can operate every project in the account; adding them gives 604, or 43.8%. AI model API keys number 149, or 10.8%. The 11 kinds add up to 1,384, five more than the total. The report does not explain the difference.

Apiiro counted 63 organizations with real secrets in public allow lists. One confirmed that its key had been valid. Examples include an admin API key from a database provider, the production Azure Postgres password of a B2B startup, and the database owner password of an IT company that builds a medical records app. There were 43 SSH credentials for public servers, some of them root passwords passed to sshpass.

Apiiro report

File size and the share with secrets

Apiiro also showed the share of files containing secrets by file size (Table 3). Each approval adds a rule, so the file grows as approvals accumulate.

File size Files Share with real secrets Estimated files with secrets
Under 500B 55,453 0.17% About 94
500B–1KB 19,770 0.51% About 101
1–2KB 13,474 1.3% About 175
2–4KB 8,449 2.8% About 237
4–8KB 4,284 5.6% About 240
Over 8KB 2,755 9.9% About 273

The estimate column is LATENT's calculation, multiplying the file count by the share. The total is about 1,120, close to the report's 1,122.

Bar chart of the share of files containing secrets by size: under 500B 0.17%, 500B to 1KB 0.51%, 1 to 2KB 1.3%, 2 to 4KB 2.8%, 4 to 8KB 5.6%, over 8KB 9.9%. Files under 1KB are 72.2% of all files and 17.4% of files with secrets. Files over 8KB are 2.6% of all files and 24.3% of files with secrets
Figure 2. Share of files containing secrets by file size. Shares from Apiiro's report; composition calculated by LATENT

At 9.9%, the share for files over 8KB is about 58 times the 0.17% for files under 500B. By file count, files under 1KB make up 72.2% of all files but only 17.4% of files with secrets. Files over 8KB are 2.6% of all files yet 24.3% of files with secrets.

The more approvals a file holds, the more times a command containing a secret has likely been approved. It is efficient to start checking with large files that hold many rules.

Apiiro report

The 215 files two scanners missed

Apiiro ran two open-source scanners, gitleaks and TruffleHog, over the 1,122 files. Gitleaks detected 564 and TruffleHog 643, and 215 were detected by neither. From these, both detected 300, gitleaks alone 264 and TruffleHog alone 343 (Figure 3).

Bar splitting the 1,122 files by scanner result: both found 300, TruffleHog only 343, gitleaks only 264, neither 215
Figure 3. Results of two scanners on the 1,122 files. Breakdown calculated by LATENT from Apiiro's figures

The detection rate is 50.3% for gitleaks and 57.3% for TruffleHog. Together they reach 80.8%, leaving 19.2%. About one file in five is not found even with both scanners.

According to Apiiro, the misses come from passwords inside commands. The two scanners look for key formats, such as provider prefixes and long random strings. A password after PGPASSWORD=, sshpass -p or mysql -p, or a curl Bearer header, looks like an ordinary word in an ordinary command. Gitleaks searches with per-rule regular expressions and entropy, and TruffleHog with per-detector regular expressions and keywords. Apiiro recommends extending scanning rules to catch passwords inside commands. The two tools were run without their verification features, and their versions and settings are not given.

GitHub's push protection stops secrets at push time. According to GitHub, 0.47% of public pushes in April to June 2026 contained secrets. Push protection stops about 30% of new secrets before they enter history, it says. Since October 13, it has blocked Anthropic API keys by default, including in free public repositories. This system, too, mainly targets keys in provider formats.

On October 28, GitHub added a classifier for secrets without fixed formats to push protection and opened a public preview. In early results, the number of pushes where it stopped secrets more than doubled. It is off by default and requires the paid GitHub Secret Protection or Advanced Security. How well it catches passwords inside commands has not been published.

gitleaks / TruffleHog / GitHub changelog

History and forks that survive deletion

In the median repository with secrets, the file had existed for 217 days as of November 2, 2026. In 118 repositories, the first commit was more than a year earlier. There are 734 secrets found only in past commits of the file and not in any current file (509 repositories). Removing a rule from the file leaves it in git history. There are also 211 forks holding the same secrets, from 74 original repositories.

Exposed keys get used quickly. In a 2023 experiment, Palo Alto Networks' Unit 42 reported attackers finding and using AWS credentials exposed on GitHub within five minutes. In Comparitech's honeypot, abuse of an AWS key began within a minute. The median of 217 days is about 310,000 minutes, more than 60,000 times five minutes. Given how long the files were public, secrets that are gone now still need to be rotated.

Keys that are not rotated stay valid for a long time. GitGuardian's 2026 report says 64% of secrets confirmed valid in 2022 were still valid in January 2026. GitHub writes that manual revocation takes about 40 days on average, and one in five takes more than 90 days.

GitHub's documentation says to revoke or rotate a secret before removing it from history. Rewriting history with git-filter-repo does not remove it from other people's clones or forks. In views GitHub has cached, the commit may still be visible by its hash.

Unit 42 / Comparitech / GitGuardian, "The State of Secrets Sprawl 2026" / GitHub blog / GitHub documentation

Files that never reach GitHub

According to Apiiro, most of these files never reach GitHub and stay on developers' machines, as plain-text JSON inside project folders. The 1,122 found in public repositories are only part of the files of this kind on developers' machines.

Attacks on files on developer machines have been reported. The npm worm Shai-Hulud, which spread in September 2025, downloaded TruffleHog onto infected machines and searched their files for secrets. In Apiiro's study, TruffleHog detected 57.3% of the 1,122 files. About three weeks earlier, malicious Nx packages had made Claude Code and Gemini CLI on developers' machines search the disk for secrets.

Some routes bypass git entirely. Apiiro lists published npm packages, Docker images built by copying whole folders, zip files and synced folders. The global git exclude that Claude Code registers has no effect on routes outside git. For an npm package, .claude/ needs to be excluded with files or .npmignore, and for Docker with .dockerignore.

Apiiro report

Comparison with other files

Apiiro also examined other files where agents leave records. Table 4 lists those where a share can be calculated by file count.

File Examined Files with real secrets Share
Chat transcripts (.specstory, aider, Cursor exports) 2,523 120 4.8%
Handoff and deploy notes 2,095 33 1.6%
.claude/settings.local.json 104,185 1,122 1.08%
Shared .claude/settings.json 76,011 298 0.39%
Horizontal bar chart of the share of files with secrets by kind: chat transcripts 4.8%, handoff and deploy notes 1.6%, .claude/settings.local.json 1.08%, shared .claude/settings.json 0.39%
Figure 4. Share of files with secrets by kind of file where agents leave records. Counts from Apiiro's report; shares calculated by LATENT

The share for the personal settings file is about 2.7 times that of the shared settings file. Most secrets in the shared settings files, too, sat in allow rules containing full commands. Chat transcripts, at 4.8%, have a higher share than the settings files. A third of the handoff notes containing secrets were written by agents themselves.

Compared with public repositories as a whole, this is a narrow slice. GitGuardian detected 28,649,024 secrets in public GitHub commits in 2025. Apiiro's 2,539 are 0.009% of that. GitGuardian puts the leak rate for commits involving Claude Code at 3.2%, against 1.5% for all public commits. We could not confirm the denominator of that comparison from the report. In a chart in the same report, leaks in commits involving Claude Code peaked at 31 per 1,000 commits in August 2025 and fell to 13 by December, roughly the same as human commits.

Apiiro report / GitGuardian report

Postman Desktop rewriting agent settings

Around the same time, another company's app was found rewriting agent settings files. On October 25, a Postman Desktop user reported on GitHub that in version 12.33.4, during an update for existing users, Postman plugins for Codex and Claude Code were installed without confirmation.

According to the report, enabling the plugin and a trust record for a startup hook were added to Codex's ~/.codex/config.toml. In Claude Code's ~/.claude/settings.json, the Postman plugin was enabled. The installer included code that tried to mark its own hook as approved. The reporter noted that this does not prove who created the trust record.

On November 5, a member of the Postman organization wrote that the change would be rolled back for now, and the founder's account closed and locked the issue. We could not find a desktop release note that explicitly mentions the rollback. Version 12.35.5 on November 6 says only "Some critical bug fixes."

This case has a different cause from Apiiro's. What they share is that agent settings files decide permissions and startup behavior. Developers need to check these files on the assumption that other apps may write to them.

Postman issue #14370

Anthropic's response

On November 7, Boris Cherny of the Claude Code team responded in the Hacker News thread. He wrote that Claude Code has not historically scrubbed secrets but that the team is looking into ways to prevent this. He explained that .claude/settings.local.json is meant to stay local, that Claude automatically adds it to the ignore list when it creates the file, and that in this case the files were created and committed by hand. Apiiro's author replied that in 539 of 1,105 repositories, a commit recording Claude as co-author had changed the file.

Cherny also wrote that permission rules are "old hat" and that everyone should use auto mode, which he said is on by default and included in all plans. He recommended enabling secret scanning whatever agent you use. In follow-up comments, he listed ideas such as having auto mode catch this and building in basic secret scanning, and said the team would prototype before shipping. To the point that auto mode still shows a prompt for sensitive commands, where the default choice "always allow" saves the approval, he replied that he was thinking about how to improve it.

As of November 8, the latest version in Claude Code's changelog is 2.1.319. Searching the changelog, we found no change that redacts secrets in approved commands before saving them.

The problem had been reported on GitHub before. Table 5 lists the main issues; none has a reply from Anthropic staff.

Issue Opened Report Closed and why
#5544 August 11, 2025 Approved commands containing credentials are saved in plain text January 3, 2026, closed by a bot after 60 days of inactivity
#11982 November 19, 2025 Creating the file in 2.0.46 does not add it to the excludes March 5, 2026, closed by a bot for inactivity
#13106 December 4, 2025 Keys in the file were pushed to a public repository December 8, 2025, closed by a bot as a duplicate of #11982
#77530 July 14, 2026 VS Code writes approvals to the shared settings file September 3, 2026, closed by a bot for inactivity
#91270 September 1, 2026 VS Code writes approvals to a tracked shared settings file November 5, 2026, closed by a bot for inactivity

Issue #91270 was closed on the day Apiiro published its report. There is earlier research outside the issues as well. In February 2026, security firm ironPeak reported finding the same file in its own repositories. Examining repositories with AI settings folders, it found secrets in history in 2.4%. It counted only secrets TruffleHog verified as valid, and the sample was small, at 100.

Boris Cherny's comment on Hacker News / Follow-up comment / Issue #5544 / Claude Code changelog / ironPeak research

Checking and fixing your own repositories

Based on Apiiro's recommendations and GitHub's documentation, here are steps for checking your own repositories. Running these commands at the project root shows the state of the settings files.

git ls-files .claude
git check-ignore -v .claude/settings.local.json
git log --all --oneline -- .claude/settings.local.json .claude/settings.json
git config --global core.excludesFile

The first line lists tracked files in .claude. If settings.local.json appears, the file has been committed. The second line shows which exclude setting keeps the file out. If nothing appears, the file is either not excluded or already tracked. The third line lists past commits that changed either settings file. The fourth shows where the global exclude file is.

The surest way to check whether permission rules contain passwords is to open the file and read it. The command shapes Apiiro listed can be found with this command.

grep -nE 'PGPASSWORD=|sshpass -p|mysql .*-p|[Bb]earer |://[^/:@ ]+:[^@ ]+@' .claude/settings.local.json .claude/settings.json

The last pattern looks for passwords in connection strings, as in postgres://user:password@host. Even if this command finds nothing, secrets without a fixed format may remain.

If you find something, deal with it in this order. First, revoke or rotate the key or password with each service. If the file was ever public, rotate even what is no longer there. Next, delete the rule lines from the file. If the file is tracked, stop tracking it with git rm --cached .claude/settings.local.json and add .claude/settings.local.json to the repository's .gitignore. To remove it from history, use git-filter-repo as GitHub's documentation recommends. Copies in forks and other people's clones remain.

Table 6 summarizes rotation steps for major services.

Service Key steps
AWS Create a second access key, switch the app to it, deactivate the old key, then delete it
GitHub Personal access tokens and similar tokens pushed to a public repository are revoked automatically
OpenAI Rotate the key on the API keys page and update production values
Anthropic Delete the key in the Console. As a GitHub secret scanning partner, keys found in public repositories are disabled automatically
Stripe Create a new key with "Rotate key," set an expiration on the old key and delete it
Supabase If a service_role key or similar leaks, fix the cause, then follow the rotation guide
npm Delete it on the Access Tokens page or with npm token delete. Revocation can take up to an hour

Database passwords and SSH passwords do not expire automatically when exposed. In Apiiro's count, 36.3% of secrets open a database directly, and rotating them is manual work for operators.

Apiiro's recommendations and the official documentation also cover prevention. If secrets are referenced through environment variables, such as $DB_URL, instead of written into commands, the rule records only the variable name. Approve patterns such as Bash(npm run test *) rather than literal commands. Add rules for passwords inside commands, such as PGPASSWORD= and sshpass -p, to pre-commit and CI secret scanning. Treat .claude/ and chat transcript folders like .env, as files that contain secrets. To keep Claude from reading .env, add Read(./.env) to permissions.deny in your settings.

GitHub: Removing sensitive data from a repository / AWS / GitHub: Token expiration and revocation / OpenAI / Anthropic / Stripe / Supabase / npm

What we will check next

There are three things LATENT will check next.

The first is a fix in Claude Code. When a version with the secret scanning Cherny mentioned ships, we will check which forms of passwords it redacts before saving. We will also check whether the VS Code extension keeps the option to write to the shared settings file.

The second is Apiiro's comparison of 16 tools. Knowing how and where other agents save approvals would show whether this type of problem is limited to Claude Code.

The third is GitHub's new classifier. Once public preview results are available, we can compare how far it reduces missed passwords inside commands against Apiiro's 19.2%.

Sources and scope

We read Apiiro's original report on November 8. The report was updated on November 8, but it does not say what changed. The report does not give the date Apiiro shared the research with Anthropic. We could not confirm why the totals by kind exceed the overall count by five, or the breakdown of the 426. The versions and settings of gitleaks and TruffleHog are not given.

Claude Code's mechanism was checked on November 8 against the official settings and permissions documentation and the changelog. Anthropic's response was checked against Boris Cherny's original comments on Hacker News through its API. We found no statement issued to the press. For GitHub issues, we checked the opening date, state and reason for closing.

The Postman case was checked against the GitHub issue, Postman's plugin repository and the release notes. For GitGuardian's 3.2% and 1.5%, we could not confirm the denominator in the report. Times until exposed keys were used come from figures published by Unit 42 and Comparitech.

Ratios, the scanner breakdown, composition and estimates by file size, and the conversion to minutes were calculated by LATENT from the figures in the sources. The checking commands were tested on sample files.