Tag: developer security

  • Claude Code settings.local.json: Secrets in 1,122 Public GitHub Copies (2026)

    Claude Code settings.local.json: Secrets in 1,122 Public GitHub Copies (2026)

    Takeaway: Apiiro researchers Shmulik Cohen and Matan Giladi report that Anthropic’s Claude Code can store the full text of an approved shell command — including passwords and API keys — in .claude/settings.local.json when a developer chooses “Yes, and don’t ask again.” Their public-GitHub scan found 104,185 copies of that file across 103,617 repositories; about 1.1% (1,122 copies) held at least one secret, totaling 1,379 distinct secrets in those files. Counting older git history, shared .claude/settings.json, and agent transcripts, they report 2,539 secrets across 1,994 repositories. Apiiro did not verify that credentials still work; one notified company confirmed a key had been live. Primary coverage: The Hacker News (Swati Khandelwal, Nov 7, 2026) and iTWire’s summary of the Nov 5 research.

    This is a developer-security story about an ordinary approval workflow — not a claim that Claude Code is deliberately exfiltrating secrets, and not a rehash of product launches like Claude Personal Finance, Anthropic message threads, or this week’s GPT-6 Cyber / Cursor Build Live Apps coverage.

    How a secret lands in settings.local.json

    By default, Claude Code asks before running most shell commands. If the user picks “Yes, and don’t ask again,” the tool saves an allow rule in the project’s .claude/settings.local.json, as described in Anthropic’s permissions documentation (summarized by THN/iTWire). Matching commands can then run without another prompt in later sessions.

    The saved rule covers only what the prompt offered. Sometimes that is a pattern (for example npm test *). Sometimes it is one exact command. When the exact command includes a password, token, or key typed on the command line, that secret is stored in plain text inside the JSON file.

    Apiiro says it reproduced the behavior with the latest models available to them (THN names Opus 5.5 and Fable 5.1). The leak path is the approval record itself: a credential used to do legitimate work becomes part of the permission that authorizes the same work next time.

    What Anthropic’s git protection does — and does not do

    Claude Code tries to keep the local settings file out of git. According to its settings documentation (as reported by THN), the first time it writes the file inside a git repository, it adds the path to the user’s global git excludes. Git on that machine then ignores the file in every repository.

    • What that helps: a single developer’s machine can stop newly written local settings from being offered for commit, without editing every project’s .gitignore.
    • What it does not do: the exclude lives in that user’s git config on that computer. It does not travel with the project the way a committed repository .gitignore does.
    • Already-tracked files: ignore rules do not untrack files already under version control. If .claude/settings.local.json was committed earlier, global excludes will not remove it from the repo or from history.
    • No project .gitignore by default: researchers say Claude Code does not add the file to the project’s own .gitignore, so teammates and CI on other machines do not inherit the protection.

    In 539 of 1,105 repositories Apiiro traced that contained secrets, a commit listing Claude as a co-author changed the settings file — evidence, in the researchers’ reading, that Claude often participates in committing the file, not that every secret was introduced by the agent.

    Apiiro’s key numbers

    MetricFigureNotes
    Public copies of .claude/settings.local.json104,185Across 103,617 repositories
    Copies with ≥1 secret1,122 (~1.1%)Format/context + AI reviewer; not live-tested
    Distinct secrets in those current files1,379THN / Apiiro
    Broader total (history + shared settings + transcripts)2,539 secrets / 1,994 reposIncludes deleted-file history and forks context
    Database passwords379Largest single category cited
    SSH logins (public servers)43Paired with reachable hosts
    GitHub / GitLab / npm tokens42Developer platform tokens
    AWS keys23Cloud credentials
    Organizations owning exposed files63Mostly software companies of all sizes
    Repos still on default branch (as of research Monday)All secret-bearing files checkedHalf present ≥217 days
    Extra secrets only in older history734 across 509 reposUsually after file deletion
    Forks carrying same secrets211 forks of 74 reposHistory/forks keep exposure alive
    Secrets in shared .claude/settings.json298 of 76,011 copiesTeams often commit shared settings on purpose
    Claude co-authored commits touching file539 of 1,105 traced reposAmong secret-bearing repos traced
    Missed by both gitleaks and TruffleHog215 of 1,122Often passwords inside ordinary commands

    Collection window cited by iTWire: public GitHub data gathered roughly Nov 1–3, 2026. Research write-up dated around Nov 5; THN’s English wrap-up ran Nov 7. Strongest cases Apiiro highlights (without publishing the secrets) include an admin-level cloud key at a database vendor and an owner password for a medical-records database — treat those as researcher examples of severity, not as confirmed breaches of those systems.

    Why scanners miss many of these secrets

    Apiiro ran gitleaks and TruffleHog over every copy without the tools’ verification step. Of the 1,122 files with a classified secret, gitleaks flagged 564 and TruffleHog 643; neither flagged 215. Most misses are passwords typed inside commands — for example after PGPASSWORD=, sshpass -p, or mysql -p — which look like ordinary words on an ordinary command line rather than known key formats.

    That matters for security teams already scanning repos: agent folders such as .claude/, .cursor/, .gemini/, and related memory/transcript paths should be treated more like .env files — on laptops as well as in repositories — and scanners need rules that catch secrets embedded in shell text, not only high-entropy token patterns.

    Claude Code vs other coding agents

    Of 16 coding agents whose documentation the researchers compared, Claude Code is the only one they confirmed saves the full approved command in a project file by default. That is a documentation-and-behavior comparison, not a claim that every other agent is free of secret sprawl — other tools may store approvals differently (user-scoped config, patterns only, redaction, etc.).

    Remediation checklist (rotate first)

    Deleting the current file does not undo a leak: older commits, forks, and clones still hold prior versions. GitHub’s usual guidance — and Apiiro’s — is to rotate credentials before cleanup theater.

    1. 1. Search: Scan your GitHub organization for .claude/settings.local.json and .claude/settings.json, and check each repository’s git history even where the files are gone.
    2. 2. Rotate: Change every password, token, and key those files have ever held. Prioritize credentials paired with a public server address.
    3. 3. Untrack: git rm --cached .claude/settings.local.json, then add the path to the repository’s own .gitignore (and org templates).
    4. 4. Scrub local rules: Open the file on each developer machine — even if it was never committed — and delete every allow rule that contains a secret.
    5. 5. Prefer env vars / secret managers: Refer to secrets as variables (for example $DB_URL) so a saved rule stores the variable name, not the literal. Putting the password in an inline ENV=secret cmd still places the secret in the command text.
    6. 6. Approve patterns, not one-off commands: Prefer pattern approvals such as Bash(npm run:*) instead of a single exact command that embeds credentials.
    7. 7. Widen the blast-radius check: Look for the same JSON inside npm packages, Docker images, zip archives, and synced folders — copies that never hit GitHub still matter on developer machines (Apiiro notes malware such as the September 2025 Shai-Hulud worm already ran TruffleHog-style scans on infected machines).

    Earlier reports and Anthropic’s response so far

    Users flagged the same behavior before Apiiro’s count. THN cites a bug report filed August 11, 2025 stating that approved commands with API keys and tokens were stored word-for-word in settings.local.json. An automated bot closed that report as “not planned” on January 3 after 60 days without activity. As of THN’s Nov 7 article, the four related reports researchers cite had all been closed by the same bot — the most recent the day before — with no Anthropic reply visible in those threads.

    iTWire also notes a February 2026 write-up from security firm ironPeak describing a committed Claude settings file that contained approved commands with database passwords and API keys, plus a tool aimed at finding secrets in AI configuration files and their history. Those earlier reports support the mechanism; they do not independently re-count Apiiro’s 2026 repository totals.

    What this is — and what it is not

    ClaimStatusCaveat
    Exact approved commands can be saved in .claude/settings.local.jsonConfirmed by docs + research reproductionOrdinary “don’t ask again” workflow
    1,122 public copies with ≥1 secret; 1,379 distinct in those filesApiiro findingClassification, not live auth tests
    Broader 2,539 secrets / 1,994 reposApiiro findingIncludes history, shared settings, transcripts
    Global git excludes protect newly written files on that machineDocumented Anthropic behaviorDoes not fix already-committed files or other machines
    Credentials still usable / systems breachedNot established by ApiiroOne notified company confirmed a key had been live
    Only Claude Code among 16 compared saves full command to a project file by defaultApiiro documentation comparisonOther agents may store approvals differently

    FAQ

    What is .claude/settings.local.json?

    A project-local Claude Code settings file. When you approve a Bash command with “Yes, and don’t ask again,” Claude Code can write an allow rule there so matching commands skip the prompt later. If the saved rule is an exact command that contained a secret, the secret is stored in plain text.

    Does Anthropic automatically gitignore the file in every repo?

    No. On first write in a git repo, Claude Code can add the path to the developer’s global git excludes. That is machine-local. Researchers say it does not add the path to the project’s .gitignore, and ignore rules do not protect files already committed.

    How many secrets did Apiiro find?

    In current public copies of the local settings file: 1,122 copies with secrets and 1,379 distinct secrets. Broader scope including history, shared settings, and transcripts: 2,539 secrets across 1,994 repositories. Apiiro did not prove those credentials still authenticate.

    Will deleting the file fix a public leak?

    Not by itself. Rotate every exposed credential first. Then stop tracking the file, add it to the repo .gitignore, scrub local allow rules, and plan history/fork cleanup carefully — deletion of the tip commit leaves older versions and forks intact.

    Why didn’t gitleaks or TruffleHog catch everything?

    Many secrets are ordinary passwords embedded in shell commands rather than high-entropy tokens with known prefixes. Apiiro reports 215 of 1,122 secret-bearing files were flagged by neither scanner in their non-verified run.

    Is this the same as a prompt-injection attack?

    No. Coverage describes an authorized developer workflow: you approve a command; the approval record retains the command text. The risk is accidental publication of that record, not a hostile prompt tricking the model into stealing a password.


    Sources: The Hacker News — Claude Code’s “Don’t Ask Again” file (Swati Khandelwal, Nov 7, 2026); iTWire — Apiiro Claude Code approval files (David M Williams, Nov 7, 2026), attributing research to Apiiro’s Shmulik Cohen and Matan Giladi (Nov 5). Figures above are from that reporting; Apiiro’s own blog post was not independently loaded for this article. We do not claim credentials remain valid unless an affected party confirmed it.