Przegląd techniczny dla osób audytujących bezpieczeństwo. Wszystko tutaj da się sprawdzić w kodzie źródłowym — łącznie z tym, co stawia nas w gorszym świetle i co nazywamy wprost, zamiast pomijać.
Nie ma backendu. To rozszerzenie Chrome w Manifest V3, które generuje kody TOTP/HOTP lokalnie przy użyciu OTPAuth. Nie prowadzimy serwerów, nie zakładamy kont i nie mamy kanału, którym dane użytkownika mogłyby do nas trafić.
Skoro nie ma serwera, nie ma też materiału klucza po stronie serwera, depozytu kluczy ani żadnej ścieżki odzyskiwania kontrolowanej przez nas. Jeśli ktoś zapomni hasła i zgubi kod odzyskiwania, nie jesteśmy w stanie pomóc — tak to zaprojektowaliśmy.
Ochrona hasłem jest opcjonalna i domyślnie wyłączona. Gdy jest włączona:
Dane nigdy nie są szyfrowane bezpośrednio kluczem wyprowadzonym z hasła. Rekordy szyfruje losowy klucz główny; wynik PBKDF2 tylko opakowuje ten klucz główny. Wynikają z tego dwie rzeczy i obie mają znaczenie:
Przy włączonej ochronie hasłem szyfrowany jest cały rekord konta poza identyfikatorem i odciskiem — łącznie z nazwą usługi, więc skradziony profil nie zdradza, w jakich serwisach użytkownik ma konta. Włączenie ochrony szyfruje rekordy, weryfikuje je przez odszyfrowanie i porównanie, i dopiero potem usuwa wszystkie kopie jawne: z lokalnego magazynu przeglądarki, z synchronizacji i ze wszystkich siedmiu rotowanych migawek kopii zapasowych.
Mówimy wprost, bo to ma znaczenie przy ocenie:
Krótko: to chroni dane w spoczynku. Nie broni — i nie może obronić — urządzenia, które w trakcie używania jest już pod kontrolą atakującego.
Manifest deklaruje pięć uprawnień i żadnych uprawnień hosta:
Nie ma Nie ma żadnych content scriptów, żadnych uprawnień tabs, cookies ani webRequest, ani web-accessible resources. Nic naszego nie istnieje na stronie, dopóki nie poprosisz tam o kod; to, co wtedy działa, jest wstrzykiwane dla tej jednej karty i tego jednego wywołania, na podstawie zgody, której udziela Twoje własne kliknięcie, i nie zostawia po sobie niczego.
Skanowanie QR kamerą działa na stronie rozszerzenia otwartej w karcie, a nie w okienku popup — popup jest niszczony, gdy traci fokus, a prośba o uprawnienie robi dokładnie to. Do tego nie jest potrzebne żadne uprawnienie w manifeście: używana jest standardowa prośba przeglądarki o dostęp do kamery, przyznawana dla origin rozszerzenia i odwoływalna w ustawieniach witryny, i nigdy nie pojawia się, zanim użytkownik nie otworzy skanera. Obraz jest dekodowany lokalnie, nigdy nie jest przesyłany ani zapisywany.
Sprawdzenie zegara to jedyne żądanie, które rozszerzenie wysyła samo z siebie; cała reszta poniżej dzieje się dlatego, że użytkownik w coś kliknął. Manifest V3 zakazuje zdalnego kodu, a nic z poniższych nie przenosi kont, tajnych kluczy ani wygenerowanych kodów. Pełna lista:
| Host | Kiedy | Czy przenosi dane użytkownika? |
|---|---|---|
| time.akamai.com timeapi.io cloudflare.com | Sprawdzenie rozjazdu zegara, buforowane; gdy żadne źródło nie odpowiada, Ustawienia to pokazują. Rozjechany zegar psuje TOTP. | Nie |
| authenticator.sh | Strona powitalna przy instalacji; strona opinii przy odinstalowaniu; strony pomocy i wsparcia, gdy otwiera się je z okienka rozszerzenia. | Nie (zwykłe logi serwera WWW) |
| chromewebstore.google.com | Strona w sklepie, otwierana w karcie dopiero po kliknięciu: formularz recenzji z prośby o ocenę, nasz menedżer haseł z banera promocji krzyżowej. | Nie (dla Google to wejście na stronę sklepu jak każde inne) |
| authenticator.featurebase.app | Publiczna tablica propozycji, otwierana w karcie z linku do zgłoszenia funkcji na pasku wsparcia. | Tylko to, co użytkownik tam napisze. Usługa zewnętrzna, z własnym regulaminem. |
Żadne fonty, skrypty, style ani obrazy nie ładują się z zewnętrznych hostów. Wszystko, co potrzebne do wyrenderowania interfejsu, jest w paczce.
Nic z powyższego nie trzeba przyjmować na wiarę. Rozszerzenie ma otwarty kod, a każde wydanie jest powtarzalne:
.crx z Chrome Web Store i rozpakuj gonpm ci && npm run build na Node 20 LTSdist/ z rozpakowaną paczkąPrzy każdym wydaniu na GitHubie publikujemy SHA-256 dla każdego pliku w zbudowanym dist/, jako SHA256SUMS-v<version>.txt i w formacie sha256sum — dzięki temu krok 4 sprowadza się do jednego uruchomienia sha256sum -c. Różnice powinny ograniczać się do kolejności plików w archiwach i białych znaków w zminifikowanym wyniku między wersjami łatek Node.
Zależności w czasie działania są celowo nieliczne — OTPAuth, React, jsQR, Zustand, Framer Motion i Lucide — przypięte zacommitowanym plikiem lock. SBOM w formacie CycloneDX udostępniamy na życzenie.
Zobacz kod źródłowyJesteśmy małym niezależnym dostawcą. Jeśli którykolwiek z poniższych punktów jest w waszym procesie wymogiem twardym, lepiej dowiedzieć się teraz niż po trzech tygodniach oceny:
W zamian oferujemy pełną jawność kodu, weryfikowalną kompilację, minimalny zestaw uprawnień i brak infrastruktury serwerowej, która w ogóle mogłaby przechowywać wasze dane.
Zgłoszenia podatności i pytania o bezpieczeństwo: security@authenticator.sh. Polityka ujawniania, zakres, czasy reakcji i warunki safe harbour są na stronie polityki bezpieczeństwa; co jest przechowywane i co opuszcza urządzenie, opisuje polityka prywatności.
Chętnie wypełnimy pisemną ankietę oceny dostawcy albo przejdziemy przez kod razem z zespołem bezpieczeństwa.
We wszystkim, co nie dotyczy bezpieczeństwa — instalacja, odzyskiwanie konta, pytania o rozliczenia przy wdrożeniu — zajrzyj do pomocy. Prosimy nie wysyłać tam zgłoszeń podatności: ta skrzynka nie jest traktowana jako poufna.