W czwartek 5 listopada firma Apiiro, robiąca narzędzia bezpieczeństwa dla zespołów kodujących z agentami AI, opisała mechanizm, przez który hasła i klucze API lądują w publicznych repozytoriach przez Claude Code. Gdy narzędzie pyta o zgodę na polecenie zawierające sekret, a programista wybiera „Yes, and don’t ask again”, zapisuje regułę uprawnień będącą dokładnym ciągiem tego polecenia. Z hasłem w środku. Plik z regułą, .claude/settings.local.json, leży w folderze projektu, więc commituje się razem z kodem. Ze skanów GitHuba z 1-3 listopada wyszło 104 185 publicznych kopii tego pliku, z czego 1122 zawierają realny sekret: klucz w znanym formacie dostawcy albo hasło przy publicznym hoście. Wątek na Hacker News z 7 listopada urosł w moim odczycie z niedzieli rano do 403 punktów, a Boris Cherny, szef Claude Code w Anthropicu, odpowiedział osobiście i wracał do dyskusji przez weekend, dziesięcioma komentarzami. Artykuł Apiiro zaktualizowano 8 listopada właśnie o tę odpowiedź. Poniżej: mechanizm, liczby, odpowiedź Anthropicu i checklista na własne repozytorium.
- Najważniejsze informacje
- Jak hasło trafia do pliku ustawień
- Dlaczego plik wychodzi poza maszynę
- Skala: ile sekretów wyszło na jaw
- Czego nie widzą skanery haseł
- Odpowiedź Anthropicu
- Jak sprawdzić własne repozytorium
- Co z tego wynika w Polsce
- Najczęstsze pytania
Najważniejsze informacje
| Co | Szczegóły |
|---|---|
| Mechanizm | Zgoda „Yes, and don’t ask again” przy poleceniu powłoki zapisuje pełny ciąg polecenia jako regułę allow w pliku settings.local.json w folderze .claude/ projektu (dokumentacja Claude Code, odczyt 8.11.2026) |
| Skala | 104 185 publicznych kopii pliku w 103 617 repozytoriach; 1122 pliki (1,1%) z realnym sekretem, 1379 odrębnych sekretów; ze wszystkimi ścieżkami łącznie 2539 sekretów w 1994 repozytoriach |
| Organizacje | 63, od grup studenckich po agencje softwareowe i dostawców IT; jedna potwierdziła Apiiro, że jej klucz był aktywny; zgłoszenia do właścicieli 2-3.11 |
| Commity Claude’a | W 539 z 1105 repozytoriów z sekretem plik zmienił commit współtworzony przez Claude’a; commity wymieniają modele od Sonnet 4.5 do Opus 5.5 |
| Skanery haseł | gitleaks wykrył sekrety w 564 z 1122 plików, TruffleHog w 643; 215 plików nie wykrył żaden, bo hasła siedzą w środku zwykłych poleceń |
| Odpowiedź Anthropicu | Boris Cherny na HN 7.11 i w weekend: „looking into what we can do to prevent this”; prototypy: wyłapywanie tego w auto mode i podstawowe skanowanie sekretów |
| Wątek HN | „Claude Code’s Don’t Ask Again exposes passwords in 1,122 public GitHub files”, 403 pkt (odczyt 8.11 rano) |
| Prasa PL | Trzy notki do 8.11 (Martin Cid Magazine, Devstock Academy, ITHardware); analiz z liczbami i odpowiedzią Anthropicu brak |
Jak hasło trafia do pliku ustawień
Scenariusz Apiiro wygląda znajomo. Na maszynie programisty siedzą sekrety: ciąg połączenia do bazy w konfiguracji, klucze chmurowe, token API w pliku .env. Prosisz Claude Code, żeby sprawdził, dlaczego nie działa logowanie na środowisku testowym, albo odpalił migrację, i polecenie, które agent proponuje, niesie ten sekret w środku, bo bez niego nie zadziała. Claude Code pyta o zgodę przed każdym poleceniem powłoki, wielokrotnie w sesji. Po dziesiątym przerwaniu, jak piszą autorzy badania, większość ludzi przestaje czytać treść, a hasło jest jednym słowem w długiej linijce.
Dokumentacja Claude Code potwierdza resztę dosłownie. Przy oknie zgody z opcją „Yes, and don’t ask again” narzędzie zapisuje to potwierdzenie jako regułę allow w .claude/settings.local.json, żeby nie pytać ponownie. Regułą jest sam ciąg polecenia. Przykład z wymyślonym hasłem wygląda tak:
{
"permissions": {
"allow": [
"Bash(mysql -h db.firma.pl -u raport -pTajneHaslo123 -e 'SELECT 1')"
]
}
}
Reguła trafia do pliku JSON obok kodu źródłowego i zostaje w nim do momentu, aż ktoś ręcznie usunie wpis. Apiiro wyraźnie oddziela winę narzędzia od kaprysów modelu: badacze odtworzyli zjawisko na Opus 5.5 i Fable 5.1, najnowszych modelach Anthropicu, więc to zachowanie samego narzędzia. Porównali też przy tej okazji 16 agentów kodujących i z nich tylko Claude Code zapisuje domyślnie pełne zaakceptowane polecenie do pliku w projekcie.
Dlaczego plik wychodzi poza maszynę
Claude Code próbuje trzymać ten plik lokalnie: gdy sam go tworzy w repozytorium gita, dopisuje **/.claude/settings.local.json do globalnej listy wykluczeń, tej z ~/.config/git/ignore, a nie do .gitignore projektu; jeśli plik utworzyłeś ręcznie, dokumentacja każe dopisać go tam samemu. Tylko że globalne wykluczenia żyją na jednej maszynie i nie pokrywają sytuacji, gdy folder staje się repozytorium później, gdy projekt trafia na drugą maszynę skopiowany katalogiem, ani gdy plik został już raz zacommitowany, bo regułom ignore nie podlegają pliki śledzone przez gita. O śledzonym pliku użytkownik w oknie zgody nie jest informowany, a kolejne potwierdzenia dopisują się do niego dalej.
Często plik commituje sam Claude. W 539 z 1105 repozytoriów z prawdziwym sekretem, których historię Apiiro prześledziło, plik zmienił commit współtworzony przez Claude’a, z podpisami modeli od Sonnet 4.5 do Opus 5.5. Instrukcje commitowania Claude Code zakazują modelowi commitowania plików .env i credentials.json. Własnego pliku ustawień nie ma na tej liście.
Na marginesie: nagłówek wątku HN i tytuł tego tekstu skracają łańcuch przyczynowy, więc precyzuję, jak robi to jeden z komentujących. Po samym kliknięciu „don’t ask again” nic nie wycieka; do wycieku dochodzi dopiero przez commit folderu .claude/ do publicznego repozytorium, z regułami, w których siedzą sekrety wpisane do poleceń. Autor badania zgodził się z tą korektą wprost, cofając przy okazji własne stwierdzenie o świeżym klonie, które komentujący rozebrali jako niemożliwe: plik nie przyjdzie z klonem, przenosi się przy kopiowaniu katalogu, a do commita trafia na nowej maszynie bez globalnych wykluczeń.
Skala: ile sekretów wyszło na jaw
W tych 1122 plikach siedzi 1379 odrębnych sekretów: 636 kluczy w formatach znanych dostawców oraz 743 hasła albo tokeny przy publicznych hostach. Ponad jedna trzecia otwiera bezpośrednio bazę danych: 379 haseł do baz, 122 klucze service-role Supabase z pełnym dostępem do projektu i 103 tokeny kontowe, kontrolujące całe konto. Dalej 43 pary loginów SSH do serwerów publicznych, w tym root hasłem w poleceniu sshpass, 42 tokeny GitHub, GitLab i npm, 23 klucze AWS i 6 kluczy prywatnych.
Wśród 63 organizacji są dostawca bazy danych z własnym kluczem chmurowym bez daty wygaśnięcia, startup z hasłem produkcyjnej bazy Azure Postgres, agencja softwareowa z produkcyjnym tokenem Square i firma IT od aplikacji medycznych z hasłem właściciela swojej chmurowej bazy. Jedna organizacja potwierdziła, że klucz był wciąż aktywny. Wg Apiiro większość przypadków to pojedynczy programiści; swoje klucze wystawiają też demo i warsztaty renomowanych dostawców.
Te pliki nie znikają same. Mediana wieku pierwszego commita pliku z sekretem to 217 dni wstecz od 2 listopada, w 118 repozytoriach minął ponad rok, a 211 forków 74 repozytoriów nosi te same wartości. Usunięcie pliku nie zamyka sprawy, bo historia gita pamięta: we wcześniejszych wersjach wyszły jeszcze 734 sekrety w 509 repozytoriach. Licząc razem historię, współdzielone pliki settings.json commitowane przez zespoły (76 011 kopii, 298 z sekretami), transkrypty rozmów z agentami (120 plików w 87 repozytoriach), pliki pamięci i notatki przekazania, wychodzi łącznie 2539 sekretów w 1994 publicznych repozytoriach. Poza GitHubem plik trafił m.in. do 126 z 31 053 Hugging Face Spaces.
Czego nie widzą skanery haseł
Apiiro puściło gitleaks i TruffleHog przez wszystkie 104 185 kopii. Z 1122 plików z sekretem gitleaks flagował 564, TruffleHog 643, a 215 plików nie wykrył żaden z nich. Luka wynika z konstrukcji tych narzędzi: szukają formatów kluczy, prefiksu dostawcy i długiego losowego ciągu, a hasło wpisane po PGPASSWORD=, po sshpass -p albo w nagłówku bearer w wywołaniu curl jest zwykłym słowem w zwykłym poleceniu i przechodzi.
Ten sam wzorzec żyje wszędzie tam, gdzie agent zapisuje, co wykonał: w transkryptach rozmów, plikach pamięci, notatkach przekazania. Kontekst złośliwego oprogramowania Apiiro daje osobno: robaczek npm Shai-Hulud z września 2025 sam pobrał TruffleHog i przeczesał nim pliki ofiar, a trzy tygodnie wcześniej złośliwe pakiety Nx kazały uruchomionym u ofiary Claude Code i Gemini CLI szukać sekretów na dysku. Plik opuszcza maszynę też bez gita: w paczce npm, w obrazie Dockera, w archiwum zip albo w synchronizowanym folderze.
Odpowiedź Anthropicu
Boris Cherny, szef Claude Code, napisał w wątku 7 listopada: „Historically Claude Code has not done secret scrubbing (there are many good tools for that), but we are looking into what we can do to prevent this”, czyli dotąd narzędzie nie czyściło sekretów, ale zespół sprawdza, jak temu zapobiec. Jego trzy punkty: plik jest „meant to stay local”, a Claude Code sam go ignoruje przy tworzeniu, więc wg niego kopie, które wyciekły, powstały i trafiły do repozytoriów ręcznie; reguły uprawnień to stara szkoła, bo auto mode jest bezpieczniejszy i domyślnie włączony w każdym planie; wreszcie skanowanie sekretów oferowane przez hosty warto mieć włączone niezależnie od agenta. Na pytanie o konkrety: „making sure auto mode catches this, building in basic secret scanning, a few other ideas”, z prototypowaniem przed wypuszczeniem czegokolwiek.
Ktoś zwrócił mu uwagę, że ten sam mechanizm może zadziałać w auto mode, gdy narzędzie pyta o wrażliwe polecenie, i Cherny przyznał: „Yeah good catch”. Rozdzielam też dwie relacje, bo obie mają swoich zwolenników w wątku: wg Cherny’ego pliki, które wyciekły, powstały ręcznie, wg Apiiro w 539 repozytoriach plik zmienił commit współtworzony przez Claude’a, a jego instrukcje commita nie zawierają własnego pliku ustawień na liście zakazów. Obie tezy mogą być prawdziwe naraz, ale obraz produktu wychodzi z nich inny, więc zostawiam obie ze źródłami. Model zagrożeń opisał krótko: człowiek zatwierdzający dużo poleceń się męczy, dlatego zespół doszedł do wniosku, że auto mode działa w praktyce rząd wielkości lepiej.
Jak sprawdzić własne repozytorium
Checklista Apiiro w tłumaczeniu na konkretne kroki, w kolejności, w jakiej sam bym ją odhaczał:
- Wyszukaj na GitHubie w swojej organizacji pliki
.claude/settings.local.jsoni.claude/settings.json. Każde trafienie w publicznym repo to plik, który każdy może przeczytać właśnie teraz. - Sprawdź historię repozytorium poleceniem
git log --all -- .claude/settings.local.json, nawet jeśli pliku dziś nie ma; jeśli jest w historii, jest też w każdym forku i klonie. - Przeczytaj listę allow w każdej kopii pliku na maszynie. Każdy wpis to polecenie, które zatwierdziłeś, ze wszystkim, co wpisałeś: szukaj haseł, tokenów, kluczy i ciągów połączenia.
- Znaleziono sekret: najpierw rotacja, sprzątanie potem. Usunięcie pliku nie czyści historii gita, forków ani klonów.
- Plik śledzony przez gita usuń z indeksu poleceniem
git rm --cached .claude/settings.local.jsoni dopisz go do.gitignoretego konkretnego repozytorium, nie tylko globalnie. - Przestań wpisywać sekrety do poleceń. Odwołuj się do nich jako
$VARz menedżera sekretów, żeby reguła zapisała$DB_URL, a nie hasło, i zatwierdzaj wzorce jakBash(npm run:*)zamiast pełnych poleceń dosłownych. - Włącz skanowanie sekretów na hoście (GitHub je oferuje), z regułami na hasła wewnątrz poleceń, bo standardowe skanery pilnują głównie formatów kluczy.
Zespołom bezpieczeństwa Apiiro daje krótszy wniosek: foldery agentów, .claude/, .cursor/, .gemini/, .specstory/, pliki pamięci i notatki przekazania traktuj jak nośniki sekretów na równi z .env, także na laptopach, i wpiń je do skanowania w pre-commit i CI, razem z historią. Najpierw rotuj sekrety przy publicznych hostach, bo to one faktycznie otwierają dostęp.
Co z tego wynika w Polsce
Polski internet nie przespał tematu całkiem: do niedzieli wyszły trzy notki, w Martin Cid Magazine, Devstock Academy i ITHardware, wszystkie o samym mechanizmie i liczbie plików. Analiz z pełnymi liczbami, rozdzieleniem tez Anthropicu i Apiiro albo checklistą na własne repozytorium jeszcze nie ma, więc ten tekst je uzupełnia, zamiast toczyć z nimi wyścig o pierwszeństwo. Dotyczy to w pierwszej kolejności programistów i zespołów pracujących z Claude Code na prawdziwych projektach, bo wśród 63 organizacji są agencje softwareowe i dostawcy IT, czyli też kod zlecany na zewnątrz. To kolejny tekst z naszej serii o ryzykach wokół tego narzędzia: backdoor w Cursor Marketplace pokazał ryzyko dystrybucji przez zewnętrzny rejestr, adres e-mail wysyłany w nagłówku User-Agent ryzyko wycieku identyfikatora konta, a wtyczki wgrane przez Postmana ryzyko łańcucha dostaw w integracjach. Pełny spis materiałów o tym narzędziu jest w hubie Claude.
Najczęstsze pytania
Claude code wyciek danych?
W listopadzie dzieją się dwie osobne sprawy. Pierwsza to adres e-mail konta wkładany przez model do nagłówka User-Agent, opisany u nas osobno. Druga, ta z tego artykułu, to hasła zapisywane w pliku .claude/settings.local.json przy potwierdzaniu poleceń, wyciekające, gdy folder .claude/ trafi do publicznego repozytorium. Mechanizmy są niezależne i naprawa jednego nie zamyka drugiego.
Claude code settings.local.json vs settings.json?
settings.local.json to plik osobisty: nadpisania jednego programisty w jednym projekcie, których nie commitujesz, a Claude Code dodaje go do globalnych wykluczeń gita przy własnym utworzeniu. settings.json w folderze .claude/ jest współdzielony i zespoły commitują go celowo, żeby wszystkim dawać te same uprawnienia, hooki i wtyczki. W badaniu Apiiro sekrety znalazły się w obu: 1122 lokalne pliki ze 104 185 kopii i 298 współdzielonych z 76 011.
Jak usunąć settings.local.json z gita?
Usuń plik z indeksu poleceniem git rm --cached .claude/settings.local.json, dopisz go do .gitignore repozytorium i zacommituj zmianę. To jednak nie czyści historii: plik zostaje w starych commitach, forkach i klonach, więc każdy sekret, jaki kiedykolwiek w nim siedział, trzeba zrotować, niezależnie od sprzątania.
Czy Claude Code zapisuje hasła?
Zapisuje dokładnie to polecenie, które zatwierdziłeś z opcją „Yes, and don’t ask again”; jeżeli zawierało hasło, hasło ląduje w pliku jako fragment reguły. Potwierdza to dokumentacja, a Apiiro reprodukowało zjawisko na Opus 5.5 i Fable 5.1, więc to zachowanie narzędzia, nie modelu. Ze 16 porównanych agentów tylko Claude Code robi to domyślnie z pełnym ciągiem polecenia.
Źródła
- Research Apiiro „Coding Agents Are Leaking Your Secrets to GitHub” z 5.11.2026, zaktualizowany 8.11 o odpowiedź Anthropicu (odczyt 8.11.2026; strona odrzuca żądania automatyczne za Cloudflare, treść przeczytana przez proxy czytające)
- Wątek Hacker News z 7.11.2026 „Claude Code’s Don’t Ask Again exposes passwords in 1,122 public GitHub files” (403 pkt, odczyt 8.11.2026)
- Pierwszy komentarz Borisa Cherny’ego w wątku HN (odczyt 8.11.2026)
- Komentarz Cherny’ego o planowanych prototypach: auto mode i secret scanning (odczyt 8.11.2026)
- Komentarz Cherny’ego „Yeah good catch” o wariancie w auto mode (odczyt 8.11.2026)
- Dokumentacja Claude Code, strona settings: zapis reguły allow przy „Yes, and don’t ask again” i globalne wykluczenia gita (odczyt 8.11.2026)
- Issue #5544 w repo anthropics/claude-code: sekret w zatwierdzonym poleceniu zapisany do pliku ustawień (wg wyliczenia Apiiro, razem z #11982, #13106 i #91270, zgłoszenia od sierpnia 2025 bez odpowiedzi Anthropicu)
- Artykuł Anthropicu o auto mode jako domyślnym, linkowany przez Cherny’ego (link z komentarza 8.11.2026, treści nie odczytywano osobno)
