Przejdź do głównej zawartości

Bezpieczeństwo

Szyfrowanie zero-knowledge​

Dane planu są szyfrowane po stronie klienta (AES-GCM). Klucz szyfrujący wyprowadzamy z hasła użytkownika (PBKDF2), a w planie Duo udostępniamy go między domownikami przez wymianę kluczy (ECDH). Klucz nie trafia na serwer w żadnej postaci. Nie piszemy własnej kryptografii — korzystamy z natywnego Web Crypto API przeglądarki.

Skutek: nawet z pełnym dostępem do bazy nie da się odczytać danych użytkownika bez jego hasła lub kodu odzyskiwania.

Co jest na Twoim urządzeniu​

Odblokowany klucz trzymamy w pamięci karty (sessionStorage) — dzięki temu odświeżenie strony nie pyta o hasło; znika po zamknięciu karty i przy wylogowaniu. Tam samo, i tylko do potwierdzenia „Zapisałem(am) kod", trzyma się kod odzyskiwania nowego konta — żeby przeładowanie strony go nie zgubiło (klucze już istnieją, a drugi raz kodu nie da się odtworzyć). Odszyfrowany plan jest zapisany lokalnie w przeglądarce (localStorage), bo aplikacja działa też offline — tę kopię czyścimy przy wylogowaniu i przy zmianie konta. Oznacza to, że ktoś z dostępem do Twojego odblokowanego urządzenia widzi Twoje dane — to granica szyfrowania E2E, nie jego luka. Chroń urządzenie tak, jak aplikację bankową.

Potwierdzanie dostępu domownika (pinning kluczy)​

Klucz do planu nie jest nadawany automatycznie każdemu, kto dołączy kodem zaproszenia. Osoba, która już ma dostęp, widzi prośbę „Potwierdź dostęp" z odciskiem klucza nowej osoby (skrót SHA-256 jej klucza publicznego); ten sam odcisk nowa osoba widzi u siebie na ekranie oczekiwania. Po potwierdzeniu odcisk zostaje zapamiętany w zaszyfrowanym planie, więc nikt z dostępem do bazy nie może go podmienić ani dopisać sobie „zaufania". Jeśli klucz znanej osoby kiedyś się zmieni, aplikacja zablokuje dostęp i pokaże ostrzeżenie; bezpieczna ścieżka to odpięcie i ponowne zaproszenie. Odpięcie partnera rotuje klucz planu i kasuje zapamiętany odcisk.

Domownik sprzed wprowadzenia pinningu, który ma już zapieczętowany klucz planu, nie dostaje prośby o potwierdzenie — dostęp już ma. Jego odcisk nie jest jednak zapamiętywany automatycznie: o istnieniu takiego wiersza decyduje baza, więc „zaufanie" wywnioskowane z bazy otwierałoby drogę do ataku (operator dopisuje fałszywy wiersz, potem go kasuje, a aplikacja sama pieczętuje mu klucz). Każde nowe pieczętowanie klucza planu nadal wymaga jawnego kliknięcia.

Dodatkowo aplikacja nie przyjmie planu zapisanego jawnie po włączeniu szyfrowania i nie zacznie od zera, gdy pobranie z chmury się nie uda — w obu przypadkach zobaczysz ekran „Nie udało się pobrać planu", a lokalna kopia i klucz pozostają bez zmian.

Kontrola dostępu (Row Level Security)​

W trybie chmurowym dostęp do danych egzekwuje Postgres RLS: zapytania widzą i modyfikują wyłącznie gospodarstwo, którego jesteś członkiem. Operacje takie jak tworzenie/dołączanie/opuszczanie gospodarstwa czy zapis stanu przechodzą przez funkcje security definer, które w kontrolowany sposób sprawdzają uprawnienia. RLS działa jako dodatkowa warstwa (defense-in-depth) na szyfrogramie — ogranicza, kto w ogóle pobierze rekord, choć i tak jest on nieczytelny bez klucza.

Klucze i sekrety​

  • W przeglądarce używany jest wyłącznie publiczny klucz anon, chroniony przez RLS.
  • Klucze wrażliwe (np. service-role, klucze dostawcy płatności) nigdy nie trafiają do frontendu — żyją tylko po stronie serwera (zmienne środowiskowe).
  • Brak sekretów w repozytorium.

Walidacja danych​

Każdy formularz i każdy odczyt ze stanu przechodzi przez schematy Zod — nieprawidłowe lub złośliwe dane nie trafiają do aplikacji. Teksty są oczyszczane ze znaków kontrolnych.

Hasła​

Hasła nie są przechowywane jawnie — Supabase trzyma jedynie jednokierunkowy hash (bcrypt). Nie da się ich odczytać; można je tylko zresetować lub nadpisać.

Operacje destrukcyjne​

Reset danych i usunięcie konta wymagają potwierdzenia hasłem, aby zapobiec przypadkowej utracie danych.

Transport i nagłówki​

Komunikacja po HTTPS, z nagłówkami bezpieczeństwa (m.in. CSP).