Claude Code's 'Don't ask again' file is leaking tokens into Git repos
Maya Okonkwo
When a developer picks "Yes, and don't ask again" in Claude Code, the exact shell command is saved to .claude/settings.local.json in the project folder. If that command carried a token, the token now sits in a plain file one git add . away from a remote. GitLab published a guide on November 11 covering prevention, exposure assessment and cleanup.
The problem is already measurable. In early November 2026, Apiiro reported 104,185 copies of the file in public repositories, per the GitLab post. Of those, 1,122 held at least one secret. GitLab adds that hundreds more secrets survived only in history, in files that had since been deleted. GitLab says its own infrastructure secrets are protected.
How the file gets committed
The file is an allowlist. Claude Code records approved commands under permissions.allow so the agent can rerun them without asking again. An entry for a test runner is harmless. A curl call with a token in the header is a stored credential.
{
"permissions": {
"allow": [
"Bash(npm test:*)",
"Bash(curl --header \"PRIVATE-TOKEN: <your-token>\" ...)"
]
}
}
Claude Code does try to keep the file out of version control. It does that through the developer's personal global excludes, not the project's .gitignore. A global excludes file is Git configuration on one machine. It applies on that machine only and does not travel with the repository. A rebuilt laptop or a fresh dev container starts without it, and the repository has no rule of its own to fall back on.
Four controls, set once
GitLab's guide stacks four prevention layers. Per the post, each is a setting a group owner changes once.
- A
.gitignoreentry for.claude/settings.local.json, added to repositories and to group file templates. All tiers. - A push rule that rejects the file by path, using the regex
(^|/)\.claude/settings\.local\.json$. Premium and Ultimate. - Secret Push Protection, which rejects pushes containing known token formats regardless of filename. Ultimate.
- A scan execution policy that runs GitLab Secret Detection in every project. Setting
SECRET_DETECTION_HISTORIC_SCAN: 'true'extends the scan to history. Ultimate.
Two caveats from the post decide the rollout order. Push rules check only newly added files, so a file that is already tracked passes. Clean up first, then turn the rule on. Group-level push rules also apply only to projects created afterwards. Existing projects need the rule configured one by one, which is toil worth scripting.
Layers 1 and 2 match a path. Layers 3 and 4 match content, and they look for known token formats. A credential in a format the scanner does not recognise gets past both content checks. The path rules are what catch it.
Checking for exposure
The guide gives three routes, depending on tier.
With GitLab Duo, Agentic Chat can query commit history across projects and report current and deleted copies of the file along with the secret types involved.
Without Duo, Premium and Ultimate customers can use code search. With Zoekt the query is file:\.claude/settings\.local\.json$. With Elasticsearch it is filename:settings.local.json path:.claude.
On any tier, the Commits API works:
GET /api/v4/projects/<id>/repository/commits?path=.claude/settings.local.json&all=true&follow=false
Keep follow=false. The post warns that without it, the call can return empty results for repositories with more than one page of commits. In an audit script, an empty result looks like a clean repository, which is the worst way for it to fail.
Cleanup order
Rotate first. GitLab's guide says to rotate every exposed secret at its source provider before touching any files. Deleting the file does nothing for a token that was already pushed.
Then remove the file and add the .gitignore entry. Then purge history under Settings > Repository > Repository maintenance > Remove blobs, run housekeeping, and allow about 30 minutes for objects to be pruned. Forks keep their own copies and need the same assessment and cleanup separately.
Until each repository has its own ignore rule, a clone is only as safe as the Git config on the machine that cloned it.
Source: GitLab Blog (about.gitlab.com)