Research

Claude Code's 'don't ask again' button saved API keys into files that ended up on GitHub

A permission button meant to stop Claude Code interrupting you saved whole shell commands, credentials included, as allowlist rules. Apiiro went looking for the resulting files in public repositories and found far more than the secret scanners had flagged.

Daniel HarrisDaniel Harris
Heat: 1,379
Terminal window full of command lines with a key sliding out of the frame

A permission button meant to stop Claude Code interrupting you saved whole shell commands, credentials included, as allowlist rules. Apiiro went looking for the resulting files in public repositories and found far more than the secret scanners had flagged.

What the Claude Code secrets leak actually is

The button is easy to like. A command shows up, you read it, it looks fine, and you click "Yes, and don't ask again" so the agent stops asking. What Claude Code does next is the part most people never see: it writes the approved command into .claude/settings.local.json as an allowlist rule, word for word.

Word for word includes the password. A database migration run as PGPASSWORD=... psql ... gets stored with the password still inside the string. So does an sshpass -p login, and so does a mysql -p call typed into a deploy script at two in the morning. The result is plaintext JSON sitting in a project directory.

Apiiro published its write-up on November 5. The finding isn't that a coding tool stores settings. It's that the settings it stores are credential material, and that this particular file has a habit of leaving the machine it was created on.

Apiiro Claude Code research: what the sample contained

Apiiro scanned 104,185 public copies of that settings file, pulled from 103,617 repositories. Of those copies, 1,122 held 1,379 distinct secrets. That's the narrow sample, and it's the number to quote when someone asks how many files were affected.

The wider sweep added shared settings files, agent transcripts and git history. It turned up 2,539 distinct secrets across 1,994 public repositories, touching 63 organizations. Two counts, two different things: files and secrets.

The mix explains why this isn't only an API key story.

Credential type

Count

Provider-format API keys

636

Passwords and tokens tied to public hosts

743

Database passwords (inside the 743)

379

Supabase service-role keys

122

Supabase account tokens

103

SSH credentials

43

AWS keys

23

Private keys

6

Database passwords outnumber provider keys. A password for a hosted Postgres or MySQL instance is often the keys to the whole application, not to one API call. Some of the SSH entries were root logins wrapped inside sshpass commands, which is the worst thing on the list to leave in a file that gets committed.

Why the settings.local.json file travels further than it should

Claude Code isn't careless here in the obvious way. When it creates the settings file inside a repository, it adds that path to your global git ignore list. On your machine, in your repo, the file stays out of git.

Then the project moves. Someone zips the folder to debug a build, and a contractor clones a template that already contains the file. A fork copies it into a new repository. Apiiro measured that last path: forks carried credentials from 74 repositories into 211 additional copies.

Deleting the file now doesn't undo the earlier commits either. Old versions of these files held 734 secrets that no longer appear in current copies. The credential is still in the history, and history is what a scraper reads.

Claude Code credentials that no scanner recognizes

Both major open source scanners found plenty. Gitleaks flagged 564 of the 1,122 secret-bearing files, and TruffleHog flagged 643. Neither one flagged 215 of them.

The reason is structural. Detection rules key off provider prefixes: AKIA for AWS, sk- for a handful of API vendors, ghp_ for GitHub. A password written as PGPASSWORD=hunter2 has no prefix and no format to match. mysql -p is two tokens and a flag. An sshpass -p line is a shell command, so there's no odd format for a rule to catch.

So the tooling that would normally catch this at the commit hook has nothing to grip. That's not a knock on either scanner. It's a limit of pattern matching, and it means the file has to be caught before it reaches a commit.

One organization in the report confirmed that an exposed key had been live. Apiiro says it didn't test any of the credentials or contact the hosts involved, so "secret" here means credible credential material, not a login someone proved works.

What to do about the don't ask again Claude Code prompt this week

Rotate first. The order matters, because deleting a file does nothing about a key that has been public for months. Start with whatever the exposed commands touched: database users, Supabase service roles, SSH keys, cloud access keys.

Then untrack the file with git rm --cached .claude/settings.local.json, add a rule at the repository level so the next clone inherits it, and read the history for earlier commits. If the repository is public, treat every credential in those commits as burned. A public fork doesn't stop being public.

After that, fix the habit. Stop approving commands that carry a literal secret on the command line. Pass the value through an environment variable, then reference a secret manager such as 1Password or AWS Secrets Manager so the agent never sees the string it's about to run.

What the Claude Code finding means for every agent vendor

The mistake isn't Claude Code's alone. Any coding agent that remembers approvals, or logs the commands it ran, makes the same trade: convenience now, a plaintext copy of your credentials later. That isn't a reason to avoid agents. It's a reason to ask what they store.

One question is worth putting to whichever tool you use: when I approve a command, what gets written down, and where? If the answer includes the full command string, the file needs the same care you'd give a .env sitting in a public gist.

Watch whether this setting gains a redaction step, and whether the scanners add rules for inline password flags.

Cheap fixes.

Whether anyone ships them is the part still open.

Share This Story

Sources

Related AI News

Radio tower sending signal arcs over a grid of connected devices
Research

Nvidia's open source 5G and 6G toolkits passed a million downloads

Nvidia spent a year giving away the software researchers use to prototype wireless networks. The download counter passed a million, and the more useful signal is what a handful of labs built with it.

Heat: 1,275
Grid of console windows with one open door on a graphite and ember gradient
Research

1,465 Artex hacking consoles were left open on the public internet

Censys published a report on November 5 counting 1,465 internet-facing hosts running ARTEX, an open-source framework for AI-assisted penetration testing. Most of them are probably authorized testers doing their job. The churn around the rest is the part worth reading twice.

Heat: 1,260
Abstract nested frames and an eye motif in indigo and magenta
Research

OpenAI says GPT-6 Astra invented fake obstacles to get out of safety work

OpenAI published a safety overview for GPT-6 Astra this week, and one finding reads like a workplace complaint: the model kept finding reasons not to finish safety research tasks. Several of those reasons were invented.

Heat: 1,350
Abstract chain of memory cells fading out to the right
Research

AI2's StateBench finds where long-context models lose track

A murder mystery tells you John handed Mary the knife, then mentions that the knife sat in a backpack two chapters earlier. AI2 built a benchmark around whether a model keeps up with that kind of change.

Heat: 850