← Wszystkie testy
BezpieczeństwoTypowa waga: Krytyczny

Skaner sekretów w JavaScript

Przeszukuje JavaScript w przeglądarce w poszukiwaniu ujawnionych kluczy API i danych logowania, np. Stripe, AWS czy Supabase.

Co sprawdza

Ten skaner przegląda kod JavaScript, który twoja strona wysyła do przeglądarki, szukając wzorców kluczy API i danych uwierzytelniających, takich jak te od Stripe, AWS czy Supabase. Wskazuje sekrety, które przez pomyłkę trafiły do kodu po stronie klienta. Sprawdza tylko to, co i tak jest publiczne dla każdego odwiedzającego.

Dlaczego to ważne

Wszystko, co trafia do JavaScriptu w przeglądarce, jest widoczne dla każdego, kto otworzy narzędzia deweloperskie. Tajny klucz w tym miejscu może posłużyć do dostępu do twoich usług, wydawania twoich pieniędzy albo odczytu danych twoich użytkowników. To bardzo częsty błąd, gdy mieszają się zmienne serwerowe i klienckie.

Jak to naprawić

Przenieś wszystkie tajne klucze na serwer i korzystaj z nich tylko z poziomu backendu, nigdy z kodu przeglądarki. Na kliencie używaj wyłącznie kluczy publicznych lub ograniczonych i zmień każdy sekret, który już został ujawniony. W wielu frameworkach zmienne bez publicznego prefiksu pozostają tylko na serwerze.

Jak działa ta kontrola

Scanaris ładuje Twoją stronę główną, zbiera pliki JavaScript, które linkuje z Twojej własnej domeny, i czyta je w poszukiwaniu wzorców znanych poświadczeń: sekretnych i ograniczonych kluczy Stripe (sk_live_, rk_live_), identyfikatorów dostępu AWS (AKIA…), kluczy API Google (AIza…), kluczy OpenAI, tokenów GitHub (ghp_…) i kluczy prywatnych w formacie PEM. Dekoduje też każdy znaleziony JWT i jeśli jego ładunek zawiera role: service_role, oznacza go jako wystawiony klucz serwisowy Supabase, co jest krytyczne. Klucze publiczne (pk_live_ Stripe, anon lub publishable Supabase, konfiguracja Firebase) są celowo wyłączone: są zaprojektowane, by być w przeglądarce.

Co atakujący z tym robi

Dokładnie to, co skaner, tylko masowo: istnieją boty, które pobierają JavaScript nowych domen, gdy tylko pojawią się w logach certyfikatów, i testują każdy znaleziony klucz. Sekretny klucz Stripe pozwala tworzyć zwroty albo czytać klientów; klucz OpenAI zużyć Twój limit; service_role Supabase czytać i kasować całą bazę z pominięciem polityk. Nie trzeba niczego „hakować": plik jest z definicji publiczny, dostaje go każdy odwiedzający.

Jak klucz trafia do bundle'a

Niemal zawsze przez zmienną środowiskową z publicznym prefiksem: NEXT_PUBLIC_ w Next.js, VITE_ w Vite, NUXT_PUBLIC_ w Nuxt. Framework wbudowuje te zmienne w JavaScript podczas builda, czyli dokładnie to, czego chcesz dla klucza publicznego, i dokładnie to, czego nie chcesz dla sekretnego. Druga typowa droga to wklejenie klucza do czatu Lovable, Bolta lub Cursora, żeby „podłączyć" usługę: model wpisuje go do komponentu, który go potrzebuje. Więcej w sekrety, które Twoja aplikacja wycieka w przeglądarce.

Jak to naprawić

  • Najpierw zrotuj klucz. Uznaj go za skompromitowany, nawet jeśli usuniesz go z kodu: wcześniejsze bundle wciąż są w cache'ach i w historii wdrożeń. Wygeneruj nowy w panelu usługi i unieważnij stary.
  • Przenieś wywołanie na serwer. W Next.js do Route Handlera lub Server Action; w Nuxt do ścieżki w server/api; z Supabase do Edge Function; na Netlify do funkcji. Przeglądarka wywołuje Twój serwer, a serwer z kluczem wywołuje usługę.
  • Usuń publiczny prefiks ze zmiennej i zapisz ją w panelu hostingu jako zmienną serwerową. Jeśli zmienna potrzebuje prefiksu, jest publiczna: zapytaj siebie, czy powinna być.
  • Sprawdź historię gita. Jeśli klucz kiedykolwiek trafił do repozytorium, jest w historii, nawet gdy obecny plik jest czysty.

Sprawdź, czy jest czysto

curl -s https://twojadomena.com | grep -oE 'src="[^"]+\.js[^"]*"' | cut -d'"' -f2 | head -5
curl -s https://twojadomena.com/assets/index-XXXX.js | grep -oE "sk_live_[A-Za-z0-9]+|rk_live_[A-Za-z0-9]+|AKIA[A-Z0-9]{16}|AIza[A-Za-z0-9_-]{35}|ghp_[A-Za-z0-9]{36}|BEGIN (RSA |EC )?PRIVATE KEY" | head

Pierwsze polecenie wypisuje Twoje skrypty; drugie szuka wzorców w jednym z nich. Jeśli w żadnym nic nie wychodzi, bundle jest czysty. Powtarzaj po każdym większym wdrożeniu, bo ponowne wygenerowanie przez AI może z powrotem wstawić klucz.

Często zadawane pytania

Czy klucz anon Supabase albo pk_live Stripe to problem?

Nie. Są publiczne z założenia i skaner ich nie oznacza. Twoje dane przy anon chroni RLS; Stripe przy pk_live chroni to, że służy tylko do tworzenia tokenów płatności, nie do pobierania opłat.

Oznacza klucz Google, którego używam do Maps. Czy to poważne?

Klucze AIza mogą być legalnie publiczne, jeśli są ograniczone do domeny i API w konsoli Google Cloud. Bez ograniczeń każdy może zużyć Twój limit. Ogranicz go, a realne ryzyko znika, choć wzorzec nadal będzie się pojawiał.

Już usunąłem go z kodu, a nadal się pokazuje.

Wdrożony bundle może być stary albo klucz jest w innym pliku (współdzielony chunk, skrypt zewnętrzny hostowany na Twojej domenie). Wdróż ponownie, przeskanuj jeszcze raz i w każdym razie zrotuj klucz.

Sprawdź to na swojej stronie

Przeskanuj swoją stronę za darmo i zobacz, czy ten i 44 inne testy przechodzą, z promptem naprawczym dla każdego problemu.

Przeskanuj moją stronę za darmo

Z bloga

Powiązane testy