learn deep. ship safe.Follow ByteMunSubscribe
AI Coding Tools

Claude Code approval rules exposed secrets on GitHub

Claude Code approval rules can save credentials in plaintext; rotate exposed keys before removing settings files, then fix repository-level exclusions.

Claude Code approval rules exposed secrets on GitHub — ai coding tools cover illustration

Rotate exposed credentials first. Repository cleanup comes after. Claude Code secrets can remain public long after a settings file is deleted: when a developer selects “Yes, and don't ask again,” Anthropic's AI coding assistant can save the approved shell command verbatim in .claude/settings.local.json. A password or token embedded in that command becomes part of the saved approval, right alongside the command it authorized.

Apiiro documented the exposure in research covered by The Hacker News. The researchers did not test whether the credentials still worked. One company they notified did confirm that its key had been live, while The 420.in reports no confirmed evidence of exploitation. Exposure is established; widespread use is not. Those are different findings, and neither should stand in for the other.

A saved approval can also save the credential

Claude Code normally asks permission before running most shell commands. Approving a command for repeated use saves an allow rule in the project's local settings file, so matching commands can run in later sessions without another prompt. The approval persists beyond that session.

The catch is the rule itself. Some approvals cover a command pattern; others cover one exact command, including any password or token embedded in it. Those Claude Code secrets land in the saved rule as plaintext. The developer approved execution, but the file preserves more than permission: it also preserves the credential used to execute that command.

My concern with an AI coding agent here is the extra credential-bearing file created by an ordinary approval. Authorizing a command is not the same intent as keeping its sensitive input in a project file after it finishes running. A developer may mean to do only the former.

Apiiro found commands containing secrets in public files, then reproduced the behavior with Opus 5.5 and Fable 5.1. It also compared documentation for 16 coding agents. Only Claude Code was confirmed to save the complete approved command in a project file by default. That is the scope of the finding: the agents examined, not every coding tool a developer might use.

The global Git exclusion protects one computer, not the project

When Claude Code first writes the local settings file in a Git repository, it adds the file to the user's global Git excludes. Claude Code's settings documentation says Git on that computer then ignores the file across repositories. The exclusion is personal Git configuration. It does not belong to the repository.

That boundary matters. Claude Code does not add the file to the repository's own .gitignore, and a global exclusion cannot protect a file that has already been committed. Nor does another developer inherit the first developer's personal Git settings by checking out the project. The repository carries no such protection with it.

Apiiro also traced 1,105 repositories. In 539 of them, commits listing Claude as a co-author changed the file, which the researchers interpret as evidence that Claude often commits the file itself. Co-authorship is what they observed. Who actually performed those commits is an interpretation of that signal, rather than something the co-author entry establishes on its own.

Shared settings and history widen the exposure

Local settings were not the only place to look. Apiiro found Claude Code secrets in settings files intended for sharing, too. Historical versions and saved agent conversations extended the exposure beyond the files a developer could still see in the current checkout.

FileIntended rolePublic copies examinedCopies containing secrets
.claude/settings.local.jsonLocal project settings, including saved approvals104,1851,122
.claude/settings.jsonShared settings that teams commit intentionally76,011298

The local files came from 103,617 repositories, and about 1.1% contained at least one secret. Apiiro identified 1,379 different secrets in those files. To count, a value had to match a known key format or be a password or token paired with a public server address; an AI reviewer also had to agree with the finding. The count was not simply every suspicious-looking string.

Among the findings: 379 database passwords, 43 SSH logins for public servers, 42 tokens for GitHub, GitLab and npm, and 23 AWS keys. More than a third of the credentials provided direct database access. This is not an investigation just for database administrators. The repository tokens need to be included in repository credential reviews as well.

The files belonged to 63 organizations, mostly software companies. They included a database vendor's admin-level cloud key and the owner password for a medical-records database. Every local file containing secrets was still on its repository's default branch in Apiiro's snapshot. These were not all recent additions, either: in half of those repositories, the file had been there for at least 217 days.

History exposed another 734 secrets across 509 repositories, usually in files that had since been deleted. Forks retained copies too: another 211 forks of 74 repositories held the same secrets as their originals. Including shared settings, history and saved agent chat logs brought the broader Claude Code secrets count to 2,539 secrets in 1,994 repositories.

Rotate credentials before removing the files

Deletion does not revoke a credential. It removes a file from the current checkout while leaving the password or token valid, and history and forks preserve additional copies. Rotate the exposed credentials first. Only then treat removing files from the current checkout as progress toward containing the exposure, rather than as containment by itself.

  1. Find both settings files across your GitHub organization. Search for .claude/settings.local.json and .claude/settings.json. Then examine each repository's history, including repositories where neither file appears in the current checkout. A search limited to the current tree leaves the historical copies out of the investigation.
  2. Rotate every credential the files have held. That means passwords, tokens and keys removed in earlier commits, not only the values visible now. I'd prioritize credentials paired with public servers, which Apiiro identifies as the findings that provide access. Their absence from today's file does not remove them from the rotation work.
  3. Stop tracking the local settings file. If Git currently tracks the file, use this command to remove it from Git's index while leaving the local copy on your computer:
    git rm --cached .claude/settings.local.json
  4. Add a repository-level exclusion. Put this entry in the project's own .gitignore; the user's global excludes are not a substitute for a rule in the repository:
    .claude/settings.local.json
    I'd add the same exclusion to the organization's templates, so future repositories do not depend on every developer having the right personal Git configuration.
  5. Remove local approval rules that contain secrets. Open the settings file on your computer and delete every rule containing a credential. Whether the file has ever been committed to Git does not change this step. Check the local rules either way.
  6. Check where else the file was distributed. Apiiro warns that the plain JSON file can end up in an npm package, Docker image, zip archive or synced folder. Those are additional places to check. A GitHub search alone cannot cover copies distributed through those paths.

Approve patterns without storing literal secrets

Put secrets-manager variables in commands, not literal credentials. For repeat approvals, choose command patterns instead of exact commands containing passwords or tokens. The saved rule should contain the variable reference or permission pattern. It should not contain the secret value the command uses, even if saving that exact command would avoid another approval prompt.

Apiiro gives $DB_URL as an example of a variable reference. For repeatable work, it recommends a permission pattern like the one below. This is approval-rule syntax, not a shell command. Do not copy it into a terminal expecting to execute it.

Bash(npm run:*)

A reusable approval does not inherently need a stored credential. A rule with no secret value has no credential to rotate. But intent is not enough: the investigation depends on what the saved rules actually contain, including their older versions. Inspect the rule itself. Using a variable reference in the command is not a reason to assume that reference was preserved correctly in the approval.

Can scanners miss Claude Code secrets?

A clean scanner result did not account for every exposed Claude Code secret. Passwords inside shell commands were a particular problem. Apiiro tested gitleaks and TruffleHog against the 1,122 affected local files, with both tools running without their verification step. Neither tool detected every affected file in that test.

Scanner outcomeFiles
Flagged by gitleaks564
Flagged by TruffleHog643
Missed by both tools215

Many missed values looked like ordinary passwords after PGPASSWORD=, sshpass -p or mysql -p. A detector built around known key formats does not necessarily recognize those strings as credentials. Read the table as a file-detection result for this test, not as a count of credentials confirmed to be active. Detection and validity are separate questions here, too.

I'd put command-embedded passwords in scanner acceptance tests before treating a clean result as clearance. Apiiro recommends scanning agent folders and memory files in pre-commit checks and CI, covering Git history as well as current files, and specifically checking that detection catches passwords inside commands. The command syntax is part of what the test needs to exercise.

The scanning scope includes .claude/, .cursor/, .gemini/ and .specstory/, on laptops as well as in repositories. Treat these artifacts like .env files. Endpoint collection is already a demonstrated concern, not just a possible extension of repository exposure: in September 2025, the Shai-Hulud worm ran TruffleHog over infected computers.

Earlier reports were closed without an Anthropic reply

A bug report filed on August 11, 2025 had described the same behavior already. Approved commands containing API keys and tokens were being stored verbatim in the local settings file. The report did not receive activity for 60 days, after which an automated bot closed it as “not planned.”

According to the researchers, the same bot had closed all four related reports cited in Apiiro's research by the time of the research. None had received an Anthropic reply. I wouldn't treat an automated issue closure as evidence that credential persistence has changed. Check the approval rule Claude Code actually saves on your computer, then inspect the rule's contents for the credential.

Frequently asked questions

Does deleting settings.local.json revoke an exposed API key?

No. Rotate the key first. Deleting the file does not invalidate the credential, and copies can remain in Git history, forks or other distributed artifacts.

Is .claude/settings.json safe to commit?

It is intended for shared settings, but its contents still need review. Apiiro found secrets in 298 of 76,011 public copies, mostly inside allow rules.

Did Apiiro confirm that every exposed credential was active?

No. The researchers did not verify whether all credentials still worked. One notified company confirmed that an exposed key had been live, while The 420.in reports no confirmed evidence of exploitation.

Do developers need to disable all repeat approvals?

Apiiro recommends approving command patterns rather than exact commands containing credentials, and using secrets-manager variable references instead of literal values. Review the saved rule to confirm it contains no secret.

Sources: Claude Code's “Don't Ask Again” File Exposes Passwords and Keys in 1,122 Public Copies on GitHub, Claude Code Permission Feature Exposes 2,539 Secrets Across GitHub Repositories - The 420.in, 11 Real Stories: How Identity Exposure Unlocks Active Attack Paths Map cross-domain privilege escalation to sever breach

How we research, write and check articles

Written by

· Senior Software Engineer

Deepak Kumar is a Senior Software Engineer based in New Delhi. He builds Generative AI into production: RAG on MongoDB Atlas Vector Search, semantic search over an editorial archive, and the multi-agent pipelines behind ByteMuni itself. He started ByteMuni to publish clear, source-checked guides for working developers.