Files
rustpad/SECURITY_CHANGES.md
T

4.6 KiB

RustPad — analiza i lista poprawek

Zrealizowane zmiany

1. Kontrola Origin dla WebSocketów

  • Żądanie upgrade jest odrzucane kodem 403, gdy brakuje nagłówka Origin, ma on wartość null, jest nieprawidłowy albo wskazuje inną domenę.
  • Porównywane są schemat i authority z rzeczywistym nagłówkiem Host.
  • X-Forwarded-Host nie jest używany do autoryzacji, aby nie dopuścić do obejścia przez sfałszowany nagłówek.
  • Gdy reverse proxy przekazuje X-Forwarded-Proto, schemat Origin musi być z nim zgodny.
  • Kontrola obejmuje WebSockety workspace i pojedynczej notatki.

2. Tokeny konta poza localStorage

  • Token konta jest wydawany wyłącznie jako ciasteczko __Host-rustpad_session z flagami:
    • HttpOnly
    • Secure
    • SameSite=Lax
    • Path=/
  • Token konta nie jest zwracany w JSON, wysyłany w wiadomości WebSocket ani przyjmowany jako token konta z Authorization.
  • Frontend usuwa stare wartości rustpad:auth-token i rustpad:access:* zawierające sekrety.
  • localStorage zawiera jedynie niesekretne znaczniki stanu.
  • Token dostępu po poprawnym haśle zasobu również trafia do ciasteczka HttpOnly; Secure; SameSite=Lax.
  • Hasło strony publicznej nie jest już zapisywane w sessionStorage.

3. Limitowanie prób

Wprowadzono odpowiedzi 429 Too Many Requests dla:

Operacja Limit szczegółowy Limit klienta Okno
Logowanie 5 prób na login 30 prób 15 min
Żądanie resetu hasła 3 próby na e-mail 10 prób 60 min
Potwierdzenie resetu 10 prób na token 20 prób 15 min
Hasło workspace/notatki 10 prób na zasób 50 prób 15 min
  • Limity haseł zasobów działają w endpointach HTTP, endpointach wydających token dostępu oraz w obu kanałach WebSocket.
  • Poprawna próba zeruje wyłącznie licznik konkretnego loginu, tokenu lub zasobu; nie zeruje limitu globalnego klienta.
  • Klucz klienta korzysta z poprawnego adresu IP przekazanego przez zaufane proxy, z bezpiecznym fallbackiem, gdy IP nie jest dostępne.

4. Bezpieczne serwowanie plików

  • Obrazy rastrowe PNG, JPEG, GIF, WebP, AVIF, BMP i ICO nadal mogą być wyświetlane inline.
  • HTML, SVG, XML, PDF oraz wszystkie pozostałe typy są zwracane jako application/octet-stream z Content-Disposition: attachment.
  • Dodano X-Content-Type-Options: nosniff oraz restrykcyjny Content-Security-Policy.
  • Nazwa pliku w Content-Disposition jest sanityzowana.

5. Upload tylko dla zalogowanych kont

  • Serwer wymaga ważnej sesji konta przed przyjęciem multipart uploadu do workspace lub notatki.
  • Gość korzystający z publicznego zasobu, hasła zasobu albo linku udostępnienia nie może wgrywać plików.
  • Frontend wcześniej blokuje przycisk i wyświetla komunikat, ale kontrola serwerowa pozostaje źródłem prawdy.

6. Widok mobilny

  • Opcje edytora mobilnego używają tego samego stylu checkboxów co konfiguracja strony.
  • Usunięto zduplikowane i nieużywane reguły CSS pozostałe po poprzedniej implementacji.

Kontrola wykonania

  • Sprawdzenie składni wszystkich plików JavaScript: zaliczone.
  • Sprawdzenie pozostałości sekretów zapisywanych przez frontend: zaliczone.
  • Sprawdzenie obecności zabezpieczeń cookies, WebSocketów, uploadu, plików i odpowiedzi 429: zaliczone.
  • Sprawdzenie nawiasów i zgodności zmienionych wywołań Rust: zaliczone statycznie.
  • Sprawdzenie końcowego diffu pod kątem białych znaków: zaliczone.
  • Kompilacja, cargo fmt, cargo check i testy Rust nie zostały uruchomione, ponieważ środowisko nie zawiera toolchainu Rust.

Lista przed wdrożeniem

  1. Wdrożyć wyłącznie przez HTTPS — ciasteczka z flagą Secure nie będą działać przez zwykły HTTP.
  2. Reverse proxy musi zachowywać prawidłowy Host oraz nadpisywać, a nie ufać nagłówkom klienta: CF-Connecting-IP, X-Real-IP, X-Forwarded-For i X-Forwarded-Proto.
  3. Przy wdrożeniu unieważnić istniejące sesje kont i istniejące tokeny dostępu do zasobów. Sekret wcześniej zapisany w przeglądarce mógł zostać skopiowany przed aktualizacją.
  4. Dla wielu instancji aplikacji przenieść limiter do współdzielonego magazynu, np. Redis. Obecny limiter działa w pamięci pojedynczego procesu i zeruje się po restarcie.
  5. W CI uruchomić co najmniej: cargo fmt --check, cargo check, cargo test oraz testy integracyjne logowania, uploadu, plików i WebSocketów za docelowym reverse proxy.
  6. Zweryfikować ustawienia domen i subdomen. Jeżeli niezaufana treść może działać na subdomenie tej samej witryny, warto dodatkowo wdrożyć tokeny CSRF dla operacji modyfikujących dane.