• Tech Support ⤴
  • Projects
  • Services
    • AI Development
    • UI/UX Design
    • Web Development
    • Technology Support
    • Mobile App Development
    • Banking ATM Interfaces
    • Process Automation
    • Security Auditing
    • Local AI Servers
  • odoo ERP
get in touchStart with Eva
logo
Tech Support ⤴
Projects
Services
AI DevelopmentUI/UX DesignWeb DevelopmentTechnology SupportMobile App DevelopmentBanking ATM InterfacesProcess AutomationSecurity AuditingLocal AI Servers
odoo ERP
get in touchStart with Eva
Loading…
logo

Transforming businesses through AI-powered digital innovation and creative excellence.

Quick Links

BlogAinexProjectsContact us

Contact Us

pinDubai Digital Park, A5, DTEC - Silicon Oasisemail[email protected]phone+971 55 7538087
© 2026 aratech. All rights reserved.
Privacy PolicyTerms of ServiceCookie Policy
Home / Blog / The Password You Approved Once Is Still in the Repo

The Password You Approved Once Is Still in the Repo

Apiiro found 2,539 real secrets across 1,994 public GitHub repositories, saved there by AI coding agents clicking through their own permission prompts. The culprit is .claude/settings.local.json, and the protection that exists never travels with the code.

November 8, 2026 · Updated November 8, 2026 - 7 min read

Key Takeaways

ExpandCollapse
  • - Clicking "Yes, and don't ask again" saves the full command, secret included, into .claude/settings.local.json inside the project folder.
  • - 1,122 of 104,185 public copies of that file hold a real secret, spanning 63 organizations and 379 database passwords.
  • - Claude Code's global git exclude protects one laptop, not the repository, not a fork, and not history that already exists.
  • - gitleaks and TruffleHog missed 215 of the 1,122 exposed files because passwords inside commands look like ordinary shell.
  • - Rotate every credential first, then untrack the file, add it to the repo's own .gitignore, and approve patterns instead of exact commands.
Dark cyberpunk illustration of a terminal command line leaking neon keys into a stack of repository files

Somewhere in a public GitHub repository, a production database password is sitting in a JSON file. It has been sitting there for 217 days. Nobody wrote it on purpose. It got there because a developer asked an AI coding agent to check why staging login was failing, the agent proposed the obvious command, and the developer clicked "Yes, and don't ask again."

That click is the whole story.

On 6 November, software security firm Apiiro published research showing that this exact pattern has left 2,539 real secrets exposed across 1,994 public GitHub repositories. Among them: a database vendor's own admin cloud key with no expiry, a production Azure Postgres password, a Square production access token, and the owner password of a medical-records database. Sixty-three organizations, mostly software companies, have at least one live credential in a public allowlist. One company confirmed its key was still working when researchers called.

This is not a model problem. It is a product-behavior problem, and it is happening to teams that thought they were being careful.

The mechanism is three words long

Claude Code asks before it runs a shell command. That's the guardrail, and it's a reasonable one. But the prompt offers an option: "Yes, and don't ask again." Choose it, and Claude Code writes a permission rule into .claude/settings.local.json inside the project folder. The rule is the command string, word for word.

If the command was PGPASSWORD=hunter2 psql -h prod-db.internal -U admin, then the rule is PGPASSWORD=hunter2 psql -h prod-db.internal -U admin. The agent didn't decide to save your password. It saved your command, and your command contained your password.

Apiiro reproduced this with Anthropic's newest models, Opus 5.5 and Fable 5.1. It is the surrounding tool, not the reasoning layer. Of sixteen coding agents whose documentation the researchers compared, Claude Code is the only one confirmed to store the full approved command in a project file by default.

The protection exists, but it doesn't travel

Here's where it gets interesting, and where most write-ups stop one step too early.

Claude Code does try to keep that file out of git. The first time it writes the file inside a repository, it adds the file to your global git exclude list. On your machine, in your git config, git now ignores that path in every repository you touch. That is genuinely thoughtful engineering.

It also doesn't survive contact with reality.

Global excludes live in one user's config on one laptop. The moment the file is already committed, the exclude does nothing. It doesn't protect a clone on a colleague's machine, a folder that becomes a repo after the fact, or a fork. And Claude Code never adds the path to the project's own .gitignore, so the protection is not part of the repository at all. It never ships with the code.

Worse: in 539 of the 1,105 repos with a confirmed secret, a commit co-authored by Claude is the one that changed the file. The agent, doing what agents do, committed the work. The work included its own permission list.

What the numbers actually say

Apiiro scanned 104,185 public copies of .claude/settings.local.json across 103,617 repositories. Of those, 1,122 files (roughly 1.1%) hold a real secret: 1,379 distinct credentials. The breakdown is worth sitting with:

  • 379 database passwords and 122 Supabase service-role keys, which open a database directly
  • 103 Supabase account tokens, which control every project in that account
  • 43 SSH logins to public servers, several of them root via sshpass
  • 42 GitHub, GitLab and npm tokens, 23 AWS keys, 6 private keys

More than a third of the exposed credentials open a database. Those are not tokens you rotate on a quarterly cycle. Those are the crown jewels, sitting in a file with a friendly name.

Size correlates brutally with risk: one in ten files over 8 KB contains a real secret, against fewer than one in five hundred under 500 bytes. The longer a developer has been clicking "don't ask again," the heavier the file gets. The median exposed file was first committed 217 days before discovery. In 118 repositories, it's been over a year.

Deleting the file doesn't fix it either. Earlier versions hold another 734 secrets across 509 repositories that appear in no current copy, usually because someone did eventually delete the file. Forks make it worse: 211 forks of 74 repositories carry the same secrets as the original. This is the standard git property that surprises everyone the first time: a secret committed is a secret permanent, and a secret permanent in a public repo is a secret published.

Your secret scanner probably missed it

Here's the part security teams need to hear. Apiiro ran gitleaks and TruffleHog over all 104,185 files. Of the 1,122 that held a real secret, gitleaks flagged 564 and TruffleHog flagged 643. 215 were flagged by neither.

The blind spot is passwords inside commands. Scanners are tuned for key formats: a provider prefix, a long random string, an entropy threshold. A password after PGPASSWORD=, sshpass -p, mysql -p, or in a bearer header inside a curl call is just an ordinary word in an ordinary command line. It looks like shell, because it is shell.

And this pattern isn't confined to one file. The same research found secrets in:

  • the shared .claude/settings.json teams commit on purpose (298 of 76,011 files)
  • agent chat transcripts from .specstory, Aider and Cursor exports (120 files in 87 repos)
  • agent memory files like MEMORY.md (9 repos)
  • handoff and deploy notes (33 files, a third of them written by the agent itself)
  • VS Code Copilot auto-approve settings (9 repos)

The habit that leaks is identical everywhere: a person types a secret into a command, and an agent dutifully records the command.

What to do, in order

Rotate first. Clean up second. That ordering is not a preference; it's the only sequence that works, because the moment a credential touches a public commit it belongs to whoever read it, and history remembers.

  1. Search your org for the file. Query GitHub for .claude/settings.local.json and .claude/settings.json across every repo, and check git history for them even where the file is gone today.
  2. Rotate everything the file has ever held — passwords, tokens, keys, connection strings — before you start deleting.
  3. Untrack and ignore. git rm --cached .claude/settings.local.json and add it to the repository's own .gitignore, not just your global one.
  4. Open the file on your own laptop, committed or not, and delete every rule containing a secret. Most of these files never touched GitHub and are still plain text on disk.
  5. Stop putting secrets in commands. Reference $DB_URL from a secrets manager so the saved rule records a variable name, not a credential.
  6. Approve patterns, not commands. Bash(npm run:*) is a rule. npm run deploy --token abc123 is a leak.

For security teams, four additions: treat .claude/, .cursor/, .gemini/, .specstory/ and agent memory files as secret-bearing paths on par with .env; add them to pre-commit and CI scanning including history; put .claude/settings.local.json in your org's .gitignore template; and triage credentials paired with a public host address first, because those are the ones that grant access from anywhere.

The takeaway we keep repeating

The lesson here isn't "AI agents are dangerous." Anthropic's permission model is a sensible one, and Claude Code's global exclude shows someone thought about this specific failure. The lesson is that convenience settings quietly become storage. Every "don't ask again" is a record. Every record has a path. Every path eventually ends up in a repository, an archive, a Docker layer, or a synced folder.

If your team has been shipping with AI coding agents for a year, you almost certainly have a .claude/ directory that predates any policy you've written since. Go read it. Not the repository version — the one on the laptop in front of you. Then check what the scanners said about it, and assume they said nothing.

The command you approved once is still holding your password. It will keep holding it until you rotate it.

Table of Contents

  • ↗The mechanism is three words long
  • ↗The protection exists, but it doesn't travel
  • ↗What the numbers actually say
  • ↗Your secret scanner probably missed it
  • ↗What to do, in order
  • ↗The takeaway we keep repeating

Related Posts

A glowing neon-purple key dissolving into falling code beside a cyan-lit server door, illustrating a leaked API token opening a path into a datacentre.

The Token Was the Door: Chainalysis, Live Keys, and the Five-Minute Agent

Chainalysis has admitted its agentic breach exposed names, password hashes and live tokens for every customer, with the login page and KYT API offline while it recovers. Microsoft's telemetry shows how one AI agent went from a secret in a public GitHub repo to exfiltrated data in Azure Key Vault in five minutes, and why a leaked token is far more dangerous than a leaked password.

Necolas HamwiNecolas Hamwi
November 7, 2026 - 7 min read
Dark cyberpunk illustration of a glowing asterisk symbol unlocking a server-room door, neon purple and cyan light on a near-black background.

The Star Came Back: How a 1980 Unix Marker Became a 2026 SSH Bypass

On 5 November OpenSSH shipped 10.6p2 for a critical login bypass: send a password longer than 256 characters to an account that has no password on an Alpine host and you are inside. The chain runs from a 1980 Unix marker through a 2012 musl change and a 2016 timing fix. Here is who is exposed, how to patch in minutes, and why the vendor shipped in a single day.

Necolas HamwiNecolas Hamwi
November 6, 2026 - 7 min read
Banner image for UAE e-invoicing 2027 KYC portal and compliance guide

UAE E-Invoicing 2027: The Complete Guide to Building a Secure Digital KYC and Customer Data Collection Portal

Mandatory UAE e-invoicing begins January 2027. This guide explains the deadlines, the customer data you must collect, and how to build a secure digital KYC portal integrated with your ERP.

Necolas HamwiNecolas Hamwi
November 6, 2026 - 12 min read