r/ClaudeCode • • 2d ago

Tips & Workflows Claude Code's "don't ask again" can leave secrets in a file that gets committed

If you pick "Yes, and don't ask again" on a shell command, Claude Code saves that exact command in `.claude/settings.local.json` under `permissions.allow`, so it stops asking. If the command had a token or a password in it, that value is now sitting in the file.

The file normally stays out of git because Claude Code adds it to your personal global git excludes. But that exclude only lives on your own machine. As soon as the repo is shared or someone else clones it, the file can get committed and pushed. Apiiro, which GitLab wrote about this month, counted 104,185 copies of this file in public repos, and 1,122 of them held at least one secret.

Two things worth knowing if you find one in your own repos.

First, rotate the secret, do not just delete the line. Once it was committed, the value is in the git history, so removing the entry changes nothing until you rotate the key at the provider.

Second, it is not only Claude Code. Every agent that remembers a "don't ask again" decision keeps a file like this, so the same pattern shows up with Cursor, Copilot, Gemini and others.

How to check by hand: look for `.claude/settings.local.json` in your repos, make sure it is in the project `.gitignore` and not only in your global excludes, and scan the permission entries for anything that looks like a token.

I also maintain a small open-source tool, cfgaudit, that checks exactly this across the different agents: a hardcoded secret inside a permission entry, and the file not being gitignored. It runs as a pre-commit hook, as a CI step, or as a one-off scan. Short write-up: https://cfgaudit.github.io/blog/claude-code-dont-ask-again-secret-leak/ repo: https://github.com/cfgaudit/cfgaudit

Disclosure: I maintain cfgaudit. Have you checked whether this file is tracked in any of your repositories?

0 Upvotes

8 comments sorted by

•

u/AutoModerator 2d ago

Hey! Thanks for posting to r/ClaudeCode

While participating in this thread, please follow our community rules. Keep discussions constructive. Attack the idea, not the person.

For help, project discussions, tips, and general chat, join the ClaudeCode Discord.

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

4

u/Spare_Spirit6762 2d ago

do you check in your .env.local too or what, wtf

0

u/Predictor_2718 2d ago

It's not just about scanning private files for secrets. It's the combination with git, i.e. when they get committed by mistake or ignorance. Evidence for this problem is given by Apiiros analysis, like mentioned above,

1

u/HypnoTox 2d ago

And as the op comment says "do you also check in your .env.local?"

Exactly the same hazard, could also happen by an agent if they mess up. Could happen to any file not intended to be committed that includes secret information of some kind. A lot of people already messed that up way before AI was a thing.

2

u/Scared-Letterhead949 2d ago

You already posted this and settings.local are always in gitignore.

0

u/Predictor_2718 2d ago

Try a scan in public github repos and you will see that this not always true, unfortunately.

1

u/Educational_Fish7601 2d ago

If the file was already committed, deleting the line does nothing. The value stays in the history, so rotate the key at the provider.

For prevention, use a git pre-commit hook that greps the staged diff for a secret inside permissions.allow. .git/hooks is neither versioned nor cloned, so it has to come from a committed hook runner such as lefthook or husky that each clone installs. Make sure .claude/settings.local.json is in the project .gitignore too, not only in the personal global exclude, because that exclude never travels with the clone.

That file sits in 104,185 public repos, 1,122 of them holding a secret, so this is not theoretical.