Passwords and API keys typed into shell commands that developers approved in Claude Code are sitting in public GitHub repositories. According to research published on November 5 by Apiiro's Shmulik Cohen and Matan Giladi, as summarized by iTWire, Claude Code can keep an approved command word for word in .claude/settings.local.json. If that file is committed and pushed, the credential goes with it. The researchers classified 1,122 of 104,185 public copies of the file as containing secrets. This is an ordinary workflow that goes wrong, not a prompt injection. This post explains the mechanism, what the numbers do and do not show, and how to check and clean up your own repositories.
TL;DR
| Question | Short answer |
|---|---|
| Am I affected? | Possibly, if you ever chose "Yes, and don't ask again" on a Bash command containing a credential, and the file ended up tracked and pushed. |
| Is there a fix? | No vendor patch is cited in the reports. The fix is yours: rotate, untrack the file, clean history, and keep secrets out of command lines. |
| Does data leave my machine? | Not by Claude Code itself. The exposure happens when you commit and push the file to a public repo. |
| Were the leaked credentials tried? | No. Apiiro did not test them, so live exposure is unproven, though one notified company confirmed its key was live. |
| What should I do today? | Search your repos and history for settings.local.json, rotate anything found, and add the file to the project .gitignore. |
What does "Yes, and don't ask again" actually save?
Claude Code's settings documentation says that when Claude asks permission to run a Bash command and you choose "Yes, and don't ask again", it saves that approval as an allow rule in .claude/settings.local.json. The next time the same command comes up, it runs without a prompt.
The problem is what a "rule" contains. Apiiro reports that the saved rule is the complete approved shell command, not a redacted pattern. If you asked the agent to check a database connection and the command carried the password inline, the password is now stored in your project directory, in plaintext, as part of the permission that authorises the command next time.
An example of the shape, with a placeholder value:
{
"permissions": {
"allow": [
"Bash(psql postgres://app:[email protected]:5432/app -c 'select 1')"
]
}
}
The file is meant to be personal. The docs describe it as the project-local scope: it applies to you in one project and sits above the shared .claude/settings.json in precedence. Nothing about the file name stops git from tracking it, though.
Why is the file ending up in public repositories?
Anthropic's documentation describes a protection. The first time Claude Code writes the file in a git repository that does not already ignore it, it adds **/.claude/settings.local.json to your global git excludes file (core.excludesFile, or $XDG_CONFIG_HOME/git/ignore, or ~/.config/git/ignore). So by default Claude Code does not publish the file.
Several things can still defeat that:
- The exclude is per machine. A global excludes file belongs to one developer's computer. It does not travel with the repository the way a committed
.gitignoredoes. A teammate, a CI job or a second machine without the entry can add the file withgit add .orgit add -A. - Already tracked files are not ignored. Git's documentation states that ignore rules do not affect files already under version control. If the file was committed once, later excludes change nothing.
- Hand-created files. The docs say that if you create the file yourself and Claude Code has not written to it yet, you must add it to
.gitignoreyourself. - Other tooling. Scripts, templates and scaffolding that copy a whole
.claude/directory carry the file along.
Apiiro also traced Claude-coauthored commits that changed the settings file in 539 of 1,105 repositories it examined. That does not establish that Claude pushed every exposed credential. The pushes were commits by people, and the co-author trailer only shows that Claude took part in the commit.
What do the numbers say, and what don't they?
Per the iTWire summary of Apiiro's research:
- Apiiro collected public GitHub data between November 1 and 3.
- It examined 104,185 public copies of
settings.local.jsonand classified 1,122 (about 1.1%) as containing secrets, with 1,379 distinct secret values. - Its broader investigation, including git history, shared settings files and agent transcripts, counted 2,539 distinct secrets across 1,994 repositories.
- It notified affected organizations on November 2 and 3, and one confirmed its exposed key was live.
The caveats matter. Apiiro did not try the credentials, so the research shows exposure risk, not demonstrated compromise. Classification used format and context filters plus an LLM reviewer working on masked candidates, which is Apiiro's method and has not been independently replicated. Apiiro also sells application and agent security products. We could not load Apiiro's own post from our environment, so the figures here come from the iTWire summary above; read them as the vendor's findings.
Is this a new problem?
No. According to the iTWire report, a Claude Code issue opened in August 2025 described approved commands containing credentials being stored verbatim in the local permissions list, with a warning about accidental commits. That issue was automatically closed for inactivity in January 2026, which is housekeeping, not evidence of a fix. Security firm ironPeak reportedly described finding database passwords and API keys in a committed Claude settings file in February 2026.
So the mechanism was known. What Apiiro adds is scale: a count of how often it ends up public.
What this means if you run AI coding agents
Treat this as a secrets-in-repo incident for every project where you use Claude Code. Work in this order.
1. Look for the file in your repositories.
git ls-files | grep -E '(^|/)\.claude/settings\.local\.json$'
git log --all --name-only --pretty=format: | grep -E '\.claude/settings\.local\.json$' | sort -u
The first command shows whether it is tracked now. The second shows whether it was ever committed on any branch.
2. Inspect the allow rules. Open any copy you find and read the permissions.allow entries. Look for connection strings, Authorization headers, --password or --token flags, and inline KEY=value prefixes.
3. Rotate first, clean second. If a secret was in a pushed commit of a public repository, assume it is compromised. Revoke or rotate it at the provider before anything else. Rewriting history does not undo copies, forks, caches or scrapers.
4. Untrack and ignore.
git rm --cached .claude/settings.local.json
echo '.claude/settings.local.json' >> .gitignore
Commit a project .gitignore entry so teammates and CI do not depend on a per-machine exclude. Then purge history with your usual tool if the repo must stay public.
5. Stop putting secrets on command lines. Read credentials from the environment or a secret manager inside the command, so the saved rule contains a variable name instead of a value. Where you can, avoid "don't ask again" for commands that carry anything sensitive and approve them once per run.
6. Check organization-wide. Search your GitHub organization for the file name, including forks and archived repos, and check your CI's checked-out workspaces.
7. Consider managed settings. Anthropic documents managed settings for organizations, including deny rules such as Read(./.env), as a policy layer developers cannot override. They do not rewrite what a developer's approval saves, but they narrow what the agent may touch.
What Beam can and cannot do here
Beam does not fix this specific behavior, and we would rather say so plainly. Beam does not edit Claude Code's settings files and does not block a git commit of a file you chose to add.
What it does cover is nearby. Beam's local collector redacts known credential formats, assignments, authorization headers, URL query strings and private keys before events are stored, per the data and redaction docs, so a password in a command Beam observes should not persist in its own history. That redaction is pattern-based and not complete. For Claude Code and Codex, workspace policy can deny risky tool calls through PreToolUse hooks in enforce mode; missing or expired cached policy is fail-open. Scanning of skills and MCP configs is heuristic. Our earlier posts on stopping dangerous Claude Code commands and how API keys leak through logs and environment variables cover the practical setup.
Why this matters beyond one file
The pattern here is a permission store that doubles as a data store. Approval systems record what was allowed so that the user is not asked again, and the easiest thing to record is the exact request. When requests carry secrets, the allow-list becomes a credentials file that lives in the project tree and inherits whatever git does with the tree.
Agent configuration directories are now a routine place for sensitive material, and they get scooped up by the same git add -A habits as everything else. Related incidents we have covered show how far exposed agent-era credentials travel: 26,400 live cloud AI credentials in public repositories, and research on agents leaking secrets. A month earlier, a developer reported Postman changing their agent config, another reminder that agent config files deserve review like code does. For the wider month, see the November 2026 attacks timeline.
explainx.ai may carry broader news coverage of this story; this post focuses on the mechanism and the cleanup.
Frequently asked questions
Why does Claude Code store secrets in settings.local.json?
When you choose "Yes, and don't ask again" for a Bash command, Claude Code saves an allow rule for that command in .claude/settings.local.json. Per Apiiro, the rule can contain the whole command as typed, including a password or API key passed on the command line.
How many public repositories were affected?
Apiiro examined 104,185 public copies of the file and classified 1,122 (about 1.1%) as containing secrets, 1,379 distinct values. Its wider search including git history and transcripts counted 2,539 secrets across 1,994 repositories. These are Apiiro's figures and the credentials were not tested.
Does Claude Code gitignore this file?
Anthropic documents that Claude Code adds **/.claude/settings.local.json to your global git excludes file the first time it writes the file. That exclude lives on your machine, does not travel with the repo, and does not affect a file git already tracks.
I committed the file. Is deleting it enough?
No. Rotate any secret that appeared in it first, then remove the file and check git history, because earlier commits and forks keep the old contents.
Can Beam prevent this?
Not by itself. Beam redacts recognized credential formats before storing events and can deny risky Claude Code and Codex tool calls through hooks, but it does not rewrite Claude Code settings files or stop you from committing them. Keep secrets out of command lines.
Related reading
- Stop Claude Code dangerous commands
- API keys in logs and env vars
- How Beam watches your agents and why it stays local
- Sources: Claude Code settings docs, iTWire's report on Apiiro's research, git gitignore documentation
Figures and behavior reflect public reports and Anthropic's documentation as of November 7, 2026, and may change. Beam is a local prototype; its redaction is pattern-based and its deny is hook-based.

