'Don't ask again' bewaart ook je wachtwoord
7m leestijd

'Don't ask again' bewaart ook je wachtwoord

Claude Code slaat het commando dat je goedkeurt op in een instellingenbestand, inclusief het secret dat erin staat. Apiiro vond echte secrets in 1.122 openbare kopieën van dat bestand, en Anthropic wijst op een gitignore, auto mode en secret scanning. Ik testte wat ik kon: er zijn drie manieren om de gitignore heen, de scanners die ik probeerde misten de meeste wachtwoorden in commando's, en het $VAR-advies van Apiiro zelf werkt anders in de huidige versie.

bewijs1.122 openbare instellingenbestanden met een echt secret3 tools3 bronnen9 november 2026
eigen meting
Wegwerp-repo's met een eigen git-configuratie en nepwachtwoorden: de dialoog, drie routes naar git, auto mode, een variabele in het commando en twee scanners op vier regels met een wachtwoord
getest op
Claude Code 2.1.319, gitleaks 8.30.1, TruffleHog 3.99.8
gecontroleerd
9 november 2026

Dit schreef Claude Code weg nadat ik bij een databasecommando op "Yes, and don't ask again" drukte:

json
{
  "permissions": {
    "allow": ["Bash(PGPASSWORD=canary-not-a-real-password-7f3a psql *)"]
  }
}

Gefeliciteerd, je hebt nu een wachtwoordmanager. Platte JSON, geen versleuteling, en zonder ignore-regel kent na een git add ., commit en push naar een openbare repo de hele wereld je wachtwoord.

Mijn wachtwoord is nep. De wachtwoorden die Apiiro vond waarschijnlijk niet. Op GitHub telde het bedrijf 104.185 openbare kopieën van .claude/settings.local.json, en in 1.122 daarvan staat een echt secret: databasewachtwoorden, cloud keys, SSH-logins als root.

"Echt" is het woord van Apiiro. Het betekent dat de waarde het formaat van een provider heeft of naast een openbare host staat, want uitgeprobeerd hebben ze er niet één. Apiiro verkoopt ook nog eens AppSec, dus die toon mag je met een korreltje zout nemen. De methode is wel gepubliceerd, en het mechanisme kreeg ik zo aan de praat op Claude Code 2.1.319.

Zaterdag haalde het verhaal Hacker News. Boris Cherny, de baas van Claude Code, reageerde daar met drie punten: git negeert het bestand automatisch, gebruik auto mode, en zet secret scanning aan. Alle drie redelijk. Ik heb in wegwerp-repo's met een eigen git-configuratie gekeken hoe ver ze komen.

Eerst mijn eigen bestanden. De allowlist van deze repo telt 413 regels. Dat is geen beveiligingsinstelling meer, dat is een dagboek.

Volgens Apiiro zit in een op de tien bestanden boven de 8 KB een echt secret, en de mijne is 33 KB. Dus heb ik hem met de hand doorgelopen, en daarna zo'n 35 andere repo's. Alles schoon, want hier let ik altijd op. Maar die bescherming zit dan in mij en in niets anders, en één keer niet opletten is genoeg.

Eén instellingenbestand met een wachtwoord heeft vier routes: de exclude-regel stopt er één, drie halen git add

De gitignore staat in je homedirectory ​

Boris: "We automatically gitignore it when Claude creates the file, so in this case the files were manually created and checked in."

Het begin klopt. In een gewone repo zet Claude Code **/.claude/settings.local.json in je globale git excludes, en dan is het bestand weg uit git status. Zo hoort het, en zo werkt het ook.

Alleen staat die regel volgens de documentatie in een bestand in je homedirectory. De repo weet van niets. Apiiro noemt drie manieren om daaromheen te komen, en alle drie kreeg ik werkend:

SituatieWat git met het wachtwoord doet
Gewone repo, zelfde machinenegeert het
Zelfde project, geen exclude-regel (gekopieerd, in een container)git add . zet het klaar voor de commit
Map die pas later een repo wordtgit add . zet het klaar na git init
Bestand staat al onder versiebeheernieuwe regel komt in de diff, geen waarschuwing op het scherm

De tweede rij heb ik nagebootst met een lege git-configuratie. Zo ziet een gekopieerd of gemount project eruit op een machine waar Claude Code die regel nog niet heeft gezet. De derde rij draaide ook op een machine zonder die regel: er was nog geen repo, en er kwam geen exclude-regel. In de vierde kwam de regel er wel, maar een ignore-regel doet niets voor een bestand dat git al volgt.

En dat "manually"? In die derde rij maakte Claude Code het bestand zelf aan, dus die hand kan ik niet vinden. De cijfers van Apiiro gaan over het inchecken: in 539 van de 1.105 onderzochte repo's wijzigde een commit met Claude als co-auteur het bestand. En in de changelog van Anthropic zelf staat over de self-hosted runner bij 2.1.307, van 21 oktober: "Fixed sessions with --use-anthropic-git-proxy committing a .claude/settings.local.json left in the clone by an earlier session".

Sluitend is dat niet. Een deel van die commits kan ouder zijn dan de exclude-regel: een issue uit november 2025 citeert de belofte al. Preciezer krijg ik het niet, al is het mediane bestand bij Apiiro pas maanden later voor het eerst gecommit.

Een commit zegt ook niet wie het bestand heeft aangemaakt, en of Claude het zelf commit, heb ik niet getest. Maar in bijna de helft van de onderzochte repo's wijzigde een commit met Claude als co-auteur het bestand, en dan dekt "manually" de lading niet.

In augustus schreef ik over Claude Code-configuratie delen met je team dat een bestand dat met de hand of met de Write-tool is gemaakt langs de exclude-regel komt. Er zijn dus meer wegen, en mijn advies van toen wordt er alleen dringender van: zet de regel in de .gitignore van de repo zelf. Dan gaat hij mee met het project.

Auto mode slaat het bestand over, tot hij jou iets vraagt ​

Boris: "Permission rules are old hat. Everyone should be using auto mode instead."

Voor iets dat old hat is, heeft dat bestand wel 104.185 openbare kopieën op GitHub.

Tegen dit lek helpt auto mode inderdaad. Hij is nu de standaard (de dialoogtests draaide ik in manual mode), en hetzelfde commando draaide daarin zonder dialoog, zonder regel en dus zonder bestand. Eén run, één commando, op Haiku 5.5, maar het is beter dan een dialoog die je na een tijdje wegklikt.

Het gat zit waar auto mode de beslissing toch weer bij jou legt. Een lezer wees daarop: "This still presumably happens in auto mode as it asks for sensitive commands". Boris antwoordde: "Yeah good catch." Die route heb ik niet nagebouwd, dus hier moet je het met zijn antwoord doen.

Auto mode ruimt ook niets op. Een regel die al op schijf staat, blijft staan, en in de mediane repo van Apiiro was het bestand 217 dagen voor de scan al gecommit. Wat een mode en een regel elk precies regelen, lees je in de gids over permissions. En auto mode heeft zo zijn eigen grenzen.

Scanners zoeken keys, en dit is een wachtwoord ​

Zet secret scanning aan, zei Boris. Doe dat, en weet waar het naar zoekt.

Apiiro haalde gitleaks en TruffleHog over alle 104.185 bestanden. Van de 1.122 met een echt secret markeerde gitleaks er 564 en TruffleHog 643, en 215 kwamen langs allebei. Een wachtwoord achter sshpass -p heeft geen prefix van een provider. Voor een scanner is het een gewoon woord in een gewoon commando.

Ik schreef zelf vier regels met nepwachtwoorden, en daar zat hetzelfde gat in:

Regel bevatgitleaks 8.30.1TruffleHog 3.99.8
PGPASSWORD=...gevondengemist
sshpass -p '...'gemistgemist
mysql -p...gemistgemist
Authorization: Bearer ...gemistgemist

Vier zelfgeschreven regels zeggen iets over de richting en niets over een percentage. Een controlebestand met keys in bekende formaten markeerden beide tools wel, dus aan de opstelling lag het niet. De scanning van GitHub zelf, die Boris aanraadde, heb ik niet getest.

De $VAR-oplossing werkt anders dan beschreven ​

Apiiro raadt aan om secrets als $VAR te gebruiken, "so the rule records $DB_URL, not the secret". Ik probeerde PGPASSWORD=$DB_PASS psql ... en psql "$DB_URL" .... In 2.1.319 wordt in beide gevallen geen regel vastgelegd, want de optie verdwijnt:

text
A variable in this command can't be checked before it runs
Do you want to proceed?
❯ 1. Yes
  2. Yes, and switch to auto mode
  3. No

Het secret blijft buiten het bestand, en daar ging het om. De prijs is dat je elke keer de vraag krijgt, tenzij je overstapt op auto mode. En van die vraag wilde je nou juist af.

Wat wel werkte: PGPASSWORD exporteren in je shell voordat je Claude Code start, zodat het commando het wachtwoord helemaal niet noemt. De dialoog bood toen psql * aan, en in het bestand kwam Bash(psql *) te staan, zonder secret. Dat is een ruime regel, dus bedenk of je die wilt.

Wat je vandaag moet nakijken ​

Dit vindt elke kopie onder je homedirectory en print de regels die op een wachtwoord in een commando lijken:

bash
find ~ -type f -path '*/.claude/settings*.json' -not -path '*/node_modules/*' \
  -exec grep -HnE 'PGPASSWORD=|sshpass -p|mysql .*-p[^ ]|Bearer |://[^/ :]+:[^@ ]+@' {} +

Het vangt alleen deze patronen, dus lees je allowlists ook zelf door. Hoe lang ze ook zijn. Daarna, in elke repo:

bash
git ls-files .claude/
git log --all --oneline -- .claude/settings.local.json .claude/settings.json
  • Secret gevonden? Eerst roteren. Het bestand verwijderen haalt het niet uit de geschiedenis, forks of clones. Apiiro vond 734 secrets die alleen nog in eerdere versies van het bestand staan.
  • Zet de ignore-regel in de repo. Voeg .claude/settings.local.json toe aan .gitignore, en draai git rm --cached als het bestand al wordt gevolgd.
  • Lees de tweede optie in de dialoog. Daar staat de regel die hij gaat opslaan, inclusief wachtwoord. Bij mij stond er Yes, and don't ask again for: PGPASSWORD=canary-not-a-real-password-7f3a psql *.
  • Zet die commandopatronen in je pre-commit hook. De grep hierboven is een goed begin, want je scanner vangt ze waarschijnlijk niet.

Boris zegt dat het team een paar aanpakken gaat uitproberen "before we ship something", met "building in basic secret scanning" als een van de opties. Mooi. Tot het zover is, beslist één klik die je een prompt bespaart ook waar je wachtwoord terechtkomt. Van alle beschermingen eromheen gaat er maar één mee met je code, en die moet je zelf toevoegen.

(11 van 11)