Security & supply chain

Claude Code's 'Don't ask again' file is leaking tokens into Git repos

Claude Code's 'Don't ask again' file is leaking tokens into Git repos

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.

  1. A .gitignore entry for .claude/settings.local.json, added to repositories and to group file templates. All tiers.
  2. A push rule that rejects the file by path, using the regex (^|/)\.claude/settings\.local\.json$. Premium and Ultimate.
  3. Secret Push Protection, which rejects pushes containing known token formats regardless of filename. Ultimate.
  4. 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)

Related
Security & supply chain

GitHub starts watching the whole public site for your leaked secrets

GitHub is previewing public monitoring for enterprise secret scanning: real-time detection across all of public github.com, with leaks attributed back to your organisation. Useful, and a preview, so read the small print.

July 6, 2026
Security & supply chain

Vault wants your AI agents to ask permission, one request at a time

HashiCorp Vault Enterprise has put a new authorization model for AI agents into public preview, built on OAuth 2.0 Rich Authorization Requests so agents must declare what they want on every call instead of inheriting long-lived secrets. For pipelines that now host coding agents, it changes who is allowed to do what at runtime.

June 27, 2026
Code quality & testing

GitLab Duo Security Review Flow goes after the logic bugs SAST leaves on the floor

GitLab moved Security Review Flow into public beta on the Duo Agent Platform. You add it to a merge request like a human reviewer, and it focuses on authorization and business-logic bugs that pattern-based scanners typically miss.

July 17, 2026

Turn this into your pipeline. Build it on Buddy.

Start free