Dla zespołów bezpieczeństwa IT i recenzentów aplikacji
Bezpieczeństwo w Peel
W skrócie: zawartość tablicy jest szyfrowana w przeglądarce kluczem zapisanym we fragmencie linku, więc nasze serwery przechowują i przekazują zaszyfrowane dane, których nie mogą odczytać. Poniżej dokładnie opisujemy, jak to działa i gdzie są granice.
Podsumowanie
- Treść karteczek, imiona, tytuły tablic, głosy i naklejki są szyfrowane algorytmem AES-256-GCM kluczem tablicy wygenerowanym w przeglądarce. Klucz podróżuje we fragmencie adresu URL (
#k=) i nigdy nie jest wysyłany na serwer. - Działania facylitatora, nagłówek tablicy i migawki są podpisywane kluczem Ed25519 facylitatora. Identyfikator tablicy jest wyprowadzany z tego klucza, więc klienci wykrywają podmianę klucza.
- Ukryte karteczki są zapieczętowane dla facylitatora (X25519 sealed box) aż do odsłonięcia i powiązane solonymi zobowiązaniami (commitments), więc odsłoniętego tekstu nie da się podmienić.
- Domyślnie anonimowo: operacje nie zawierają identyfikatora autora; głosy i reakcje używają losowego identyfikatora przypisanego do tablicy.
- Uczestnicy nigdy się nie uwierzytelniają. Żadnych SDK analitycznych, reklam ani skryptów zewnętrznych poza Paddle.js na stronie płatności.
- Wyłącznie Cloudflare. Nieprzypisane tablice są usuwane 60 dni po ostatniej wizycie.
Jak płyną dane
Fragment adresu URL (wszystko po #) obsługuje przeglądarka i nie jest on częścią żądania HTTP. Właśnie tam Peel umieszcza klucz tablicy.
Model zagrożeń
Projektujemy tak, by w pełni przejęty lub ciekawski serwer – także nasz – dowiedział się jak najmniej o tym, co mówi zespół.
Co chronimy
- Treść karteczek, wybrane GIF-y i – w trybie imiennym – imię autora.
- Imiona i awatary uczestników, nazwę tablicy i tytuły własnych szablonów.
- Kto głosował lub reagował na co i kto napisał którą karteczkę.
- Integralność retro: kroków, odsłonięć i decyzji facylitatora nie da się sfałszować.
Jakich przeciwników bierzemy pod uwagę
- Nasze własne serwery, nieuczciwego pracownika albo kogoś, kto włamie się do naszego magazynu danych: dostają zaszyfrowane dane i metadane.
- Atakującego w sieci: TLS wszędzie; klucz nigdy nie przechodzi przez sieć.
- Serwer podmieniający klucze: identyfikator tablicy jest wyprowadzany z klucza publicznego facylitatora, a klienci weryfikują podpisany nagłówek.
- Uczestnika, który chce podejrzeć lub coś sfałszować: ukryte karteczki są zapieczętowane dla facylitatora; operacje facylitatora wymagają jego podpisu; edycja karteczki wymaga jej klucza.
- Facylitatora publikującego ponownie za autora offline: zobowiązania uniemożliwiają zmianę tekstu.
Poza zakresem – uczciwie
- Każdy, kto ma link uczestnika, może czytać tablicę. Link jest kontrolą dostępu. Należy go udostępniać tak ostrożnie jak samą tablicę.
- Przejęte urządzenie, złośliwe rozszerzenie przeglądarki albo ktoś zaglądający przez ramię.
- Analiza ruchu: serwer widzi czas, rozmiary i liczniki (zob. mapę danych).
- Odmowa usługi ze strony serwera: może odrzucać lub opóźniać wiadomości, ale nie może ich czytać ani fałszować.
Kryptografia
Wszystkie prymitywy pochodzą z wbudowanego w przeglądarkę API WebCrypto. Żadnej autorskiej kryptografii, żadnych zewnętrznych bibliotek kryptograficznych.
| Klucz | Algorytm | Zastosowanie |
|---|---|---|
| K_board | AES-256-GCM, losowy 96-bitowy IV | Szyfruje każdą operację, migawkę i aktualizację obecności. Dane dodatkowe wiążą identyfikator tablicy, typ i identyfikator operacji, więc zaszyfrowanych danych nie da się powtórzyć w innej tablicy ani innym miejscu. Istnieje tylko we fragmencie linku #k=. |
| K_owner | Ed25519 | Uprawnienia facylitatora. Podpisuje operacje facylitatora (krok, timer, wyróżnienie, szablon, ustawienia, odsłonięcie głosów, ukrycie karteczki), nagłówek tablicy i migawki. Ściśle rosnący licznik blokuje ataki powtórzeniowe. Tylko w linku facylitatora (&o=). |
| Identyfikator tablicy | SHA-256, pierwsze 80 bitów, base32 | Wyprowadzany z klucza publicznego facylitatora, więc sam identyfikator dowodzi, który klucz jest właścicielem tablicy. Klienci odrzucają nagłówek, którego klucz nie daje tego identyfikatora po zahaszowaniu. |
| K_fac | X25519 sealed box: efemeryczny X25519 + HKDF-SHA256 + AES-256-GCM | Podczas pisania ukryte karteczki są pieczętowane kluczem publicznym facylitatora. Otworzyć je może tylko link facylitatora (&f=). |
| Klucze karteczek | Ed25519, jeden klucz na karteczkę | Ma go tylko autor. Edycje i odsłonięcie są nim podpisywane: autentyczność bez ujawniania tożsamości. |
| Zobowiązania | HMAC-SHA256 z losową 128-bitową solą | Ukryta karteczka publikuje zobowiązanie (commitment) do swojej treści. Przy odsłonięciu publikowane są treść i sól, a każdy klient je weryfikuje, więc nikt nie może podmienić tekstu. |
| Obecność | AES-256-GCM kluczem K_board | Imiona, awatary i wskaźniki pisania są szyfrowane jak wszystko inne. |
| Pakiet kluczy | HKDF-SHA256 z PRF klucza dostępu lub z kodu odzyskiwania, AES-256-GCM | Zalogowani facylitatorzy mogą synchronizować klucze tablic między urządzeniami. Pakiet jest szyfrowany na urządzeniu; serwer przechowuje tylko zaszyfrowane dane i opakowane klucze. |
Podpisywane wiadomości mają separację domen (np. peel/sig/v1, peel/header/v1, peel/snap/v1), więc podpisu złożonego w jednym celu nie da się użyć w innym.
Anonimowość
- Operacje nie zawierają identyfikatora autora. Serwer nie może powiązać karteczki z osobą; domyślnie facylitator też nie.
- Głosy i reakcje są przypisane do losowego identyfikatora w obrębie tablicy, niepowiązanego z imieniem.
- Wskaźniki pisania pokazują, że ktoś pisze, ale nigdy co.
- Tryb imienny to jawne ustawienie tablicy; imię autora jest wtedy przesyłane wewnątrz zaszyfrowanej karteczki.
- Uczestnicy nigdy się nie logują, więc nie ma konta, które dałoby się z czymś powiązać.
Mapa danych
Wszystko, co przechowujemy: gdzie, kto może to odczytać i jak długo.
| Dane | Gdzie | Kto może odczytać | Jak długo |
|---|---|---|---|
| Karteczki, głosy, reakcje, naklejki, działania, nazwa tablicy, tytuły własnych szablonów | Magazyn Durable Object, w postaci zaszyfrowanej | Osoby, które mają link do tablicy | Do usunięcia tablicy |
| Koperta operacji: typ, numer sekwencji i czas serwera, rozmiar, licznik facylitatora | Magazyn Durable Object | Peel | Do usunięcia tablicy |
| Imiona uczestników, awatary, wskaźnik pisania | Przekazywane w postaci zaszyfrowanej; w pamięci podczas połączenia | Osoby, które mają link do tablicy | Podczas połączenia |
| Status tablicy: krok, liczba uczestników i karteczek, identyfikator szablonu z katalogu, flaga blokady, czas utworzenia i wygaśnięcia | Durable Object, D1; wiadomości w Slacku/Teams, jeśli zainstalowano | Peel; twój kanał w Slacku/Teams | Przez cały czas życia tablicy |
| Konto facylitatora: identyfikator dostawcy, imię, e-mail (jeśli udostępniony), powiązani dostawcy, data utworzenia, sesja | D1 | Peel | Do usunięcia konta |
| Pakiet kluczy i opakowane klucze | D1, w postaci zaszyfrowanej | Tylko ty (klucz dostępu lub kod odzyskiwania) | Do usunięcia konta |
| Plan, status subskrypcji, identyfikatory klienta i subskrypcji w Paddle | D1; Paddle | Peel, Paddle | Tak długo, jak wymagają przepisy podatkowe |
| Identyfikatory przestrzeni roboczej, kanału i wiadomości w Slacku/Teams; token bota (szyfrowany AES-GCM) | D1 | Peel | Do odinstalowania |
| Adres IP | Brzeg sieci Cloudflare, przejściowo (dostarczanie, limity zapytań) | Cloudflare, ogranicznik zapytań Peel | Nie trafia do naszych baz danych |
| Dzienne liczniki (utworzone tablice, osiągnięte kroki) | D1 | Peel | Tylko zbiorczo, bez identyfikatorów |
Co nasz serwer może, a czego nie może
Może
- Widzieć typy operacji, rozmiary, czas, krok, liczbę uczestników i karteczek, identyfikator szablonu z katalogu i flagę blokady.
- Odrzucać, opóźniać lub nie dostarczać operacji (odmowa usługi).
- Widzieć adresy IP na brzegu sieci.
- Zliczać tablice i osiągnięte kroki, zbiorczo.
- Usunąć tablicę (wygaśnięcie, zgłoszenia nadużyć).
Nie może
- Czytać treści karteczek, imion, tytułów tablic, tytułów własnych szablonów, głosów ani naklejek.
- Czytać ukrytych karteczek przed odsłonięciem (ani nawet po nim).
- Fałszować działań facylitatora: wymagają jego podpisu.
- Podmienić kluczy na własne: zdradzi go identyfikator tablicy.
- Zmienić odsłoniętego tekstu karteczki: zdradzą go zobowiązania i podpisy karteczek.
- Ustalić, kto napisał którą karteczkę.
Jak w każdej aplikacji webowej, trzeba ufać kodowi, który serwujemy. Dlatego ta powierzchnia jest mała: ścisła polityka Content Security Policy, script-src ograniczony do naszej domeny, żadnych skryptów zewnętrznych, a protokół jest na życzenie dostępny do przeglądu.
Slack i Microsoft Teams
- Wiadomości zawierają link do tablicy i metadane (tytuł, krok, liczniki). Treść karteczek jest wysyłana tylko wtedy, gdy facylitator wyśle podsumowanie i to potwierdzi.
- Karta z zaproszeniem zawiera link uczestnika razem z kluczem. Każdy, kto widzi ten kanał, może dołączyć – tak samo jak po wklejeniu tam linku.
- Podglądy linków pokazują tylko krok i liczniki, nigdy treść.
- Zakresy uprawnień Slacka:
commands,chat:write,links:read,links:write;users:readtylko wtedy, gdy zespół włączy wzmianki. - Tokeny botów są szyfrowane w spoczynku (AES-GCM, klucz przechowywany jako sekret Workera). Podpisy żądań Slacka i tokeny Bot Framework są weryfikowane przy każdym żądaniu.
- Odinstalowanie aplikacji zatrzymuje wszystkie publikacje i usuwa jej tokeny.
Web i infrastruktura
- Wyłącznie Cloudflare: Pages, Workers, Durable Objects, D1, R2 i KV na koncie 1801 Labs. Żadnych innych serwerów.
- TLS wszędzie, HSTS i ścisła polityka Content Security Policy.
- Żadnych SDK analitycznych, reklam ani skryptów zewnętrznych. Jedyny wyjątek to Paddle.js, ładowany wyłącznie na stronie płatności.
- Jedno ciasteczko, tylko dla zalogowanych facylitatorów:
peel_session, httpOnly, Secure, SameSite=Lax. - Wyszukiwanie GIF-ów i multimedia idą przez nasze API, więc adresy IP uczestników nigdy nie trafiają do GIPHY.
- Fonty i zasoby hostujemy sami. Żadnych fontów z CDN, żadnych pikseli śledzących.
- Limity zapytań na IP i na tablicę; zgłoszenia nadużyć i blokada przez facylitatora.
Konta i przechowywanie danych
- Uczestnicy nigdy się nie uwierzytelniają. Facylitatorzy logują się przez Google (albo Entra ID przez Teams) tylko po to, by zachować tablice lub korzystać z płatnych funkcji.
- Konto przechowuje identyfikator, imię i e-mail od dostawcy oraz zaszyfrowany pakiet kluczy odblokowywany kluczem dostępu (WebAuthn PRF) lub kodem odzyskiwania. Logowanie daje własność, a nie dostęp do treści.
- Przypisanie tablicy do konta potwierdza własność podpisem facylitatora. Klucze tablic nigdy nie są wysyłane.
- Tablice bez konta są usuwane 60 dni po ostatniej wizycie; każda wizyta zeruje licznik. Magazyn usuwają alarmy Durable Object.
- Usunięcie konta usuwa sesje, pakiet kluczy i bibliotekę, a tablice znów wygasają po 60 dniach.
Odpowiedzialne zgłaszanie podatności
Coś znaleziono? Prosimy najpierw dać nam znać – chętnie współpracujemy. Potwierdzamy zgłoszenia w ciągu trzech dni roboczych.
- Prosimy o rozsądny czas na poprawkę (celujemy w 90 dni) przed upublicznieniem.
- Testy wyłącznie na własnych tablicach i kontach. Bez dostępu do cudzych danych i bez pogarszania działania usługi.
- Nie podejmiemy kroków prawnych wobec badań prowadzonych w dobrej wierze zgodnie z tymi zasadami.
- Kontakt w formacie do odczytu maszynowego:
/.well-known/security.txt.
Klienci planu Company otrzymują pakiet do przeglądu bezpieczeństwa (odpowiedzi na kwestionariusze, podprocesorzy, przepływy danych). DPA · Prywatność