Skip to content

fix(security): drobne wzmocnienia zabezpieczeń - #917

Merged
mpasternak merged 2 commits into
devfrom
sec/drobne-hardening
Oct 24, 2026
Merged

mpasternak merged 2 commits into
devfrom
sec/drobne-hardening

Conversation

@mpasternak

@mpasternak mpasternak commented Oct 24, 2026 •

Copy link
Copy Markdown
Member

Zestaw drobnych wzmocnień zabezpieczeń (hardening). Każdy punkt ma test.

Zmiany

  1. /test_403/, /test_500/, /test_exception/ są dostępne tylko dla superużytkownika (bpp.views.sentry_tester.tylko_superuser). Anonim trafia na logowanie, pozostali zalogowani dostają 403.
  2. ROLLBAR_SCRUB_FIELDS: dodane pbn_token, csrfmiddlewaretoken, sessionid, ott, pbn_app_token, orcid_client_secret, dspace_api_password i clarivate_password. access_token, refresh_token i client_secret były już na liście.
  3. Reset hasła:
    • liczniki są atomowe (cache.add + cache.incr),
    • limit per IP bez zmian (5/h, 429),
    • nowy limit per adres e-mail: 3/h, klucz to SHA-256 znormalizowanego adresu. Po przekroczeniu użytkownik dostaje to samo przekierowanie co zwykle, tylko mail nie wychodzi,
    • nowy BppPasswordResetForm nie zgłasza błędu dla adresu bez konta (zachowanie jak w django.contrib.auth).
  4. secret_key_guard odrzuca wartość build-time-only-not-used, chyba że ustawiono DJANGO_BPP_BUILD_STAGE=1. W Dockerfile flaga jest ustawiona inline w obu RUN-ach collectstatic (nie przez ENV). To odwraca wcześniejszą decyzję z fix(security): hardening z równoległego security review (6 findingów) #610, w której wartość build-owa była przepuszczana zawsze.
  5. ewaluacja_dwudyscyplinowcy wymaga uprawnień „wprowadzanie danych” lub superużytkownika. To ta sama bramka URLconf co w ewaluacja_optymalizacja, skąd prowadzi link. Widok pokazuje wszystkich autorów, więc ma_uprawnienia_ewaluacji (dostęp dla każdego konta powiązanego z autorem) byłby za szeroki.
  6. stan_systemu: group_required używa teraz GR_WPROWADZANIE_DANYCH. Wcześniej była tam nazwa nieistniejącej grupy, więc przechodził tylko superużytkownik. Moduł jest używany: odpytuje go htmx z ekranów ewaluacji i snapshotów.
  7. Eksport multiseek zostaje z csrf_exempt. Widok przyjmuje tylko GET (http_method_names = ["get"]) i nie ma efektów ubocznych. Test pilnuje, że POST zwraca 405.
  8. Szczegóły metryk: dane wykresów idą przez filtr jsonify zamiast json.dumps|safe.
  9. COinS: rft.language jest kodowany przez quote().
  10. rodzaj_autora_label składa HTML przez format_html; z szablonu zniknęło |safe.
  11. admin_tools: podpięty jest tylko admin_tools/dashboard/. Trasy zakładek menu nie są montowane, bo BPP nie używa zakładek.
  12. rekord_short w adminie: najpierw safe_tytul_html, potem Truncator(...).chars(100, html=True).
  13. Usunięty nieużywany kod: formatted_komunikat w pbn_export_queue oraz pbn_api/admin/helpers.py razem z jego testem.
  14. Nagłówek CSP z nowego middleware django_bpp.csp, bez nowych zależności:
    • domyślnie włączony w trybie Content-Security-Policy-Report-Only,
    • konfiguracja przez DJANGO_BPP_CSP_ENABLED, DJANGO_BPP_CSP_REPORT_ONLY, DJANGO_BPP_CSP_POLICY i DJANGO_BPP_CSP_REPORT_URI,
    • opis w docs/administrator/zaawansowane.md.

Ryzyka zmiany zachowania

  • Reset hasła: adres bez konta nie pokazuje już komunikatu „brak konta”, tylko zwykłe potwierdzenie. Po 3 żądaniach na ten sam adres w ciągu godziny kolejne maile nie wychodzą.
  • Reset hasła, konta bez lokalnego hasła: konta bez używalnego lokalnego hasła (np. logowanie LDAP/Microsoft/ORCID) nie dostają już komunikatu o braku możliwości resetu, tylko zwykłe potwierdzenie (mail nie wychodzi).
  • Dwudyscyplinowcy: użytkownicy powiązani z autorem, ale spoza grupy „wprowadzanie danych”, tracą dostęp.
  • Stan kolejki denorm: redaktorzy z grupy „wprowadzanie danych” zyskują dostęp. Wcześniej dostawali przekierowanie.
  • Klucz build-owy: wdrożenie z DJANGO_BPP_SECRET_KEY=build-time-only-not-used nie wystartuje na settings.production. CI nie buduje stage testserver, więc zmiana w Dockerfile nie jest tam weryfikowana; pilnuje jej test statyczny pliku.
  • CSP: przeglądarki będą logować naruszenia w konsoli (Report-Only, nic nie jest blokowane). Jeśli nginx już ustawia CSP, można wyłączyć ten nagłówek przez DJANGO_BPP_CSP_ENABLED=false.

Testy

Lokalnie:

  • nowe i powiązane moduły (ewaluacja_metryki, templatetags, multiseek, rollbar, menu, secret_key_guard, password reset, stan_systemu, dwudyscyplinowcy): 308 passed,
  • pbn_export_queue/, pbn_api/tests/, bpp/tests/test_admin/ i ewaluacja_optymalizacja/tests/test_authz.py: 1349 passed,
  • Playwright test_smoke.py (anonimowy crawl przechodzi przy aktywnym CSP Report-Only): 1 passed.

Nowe testy przed poprawką kończyły się błędem: 38 failed i błąd importu w teście guarda.

🤖 Generated with Claude Code

https://claude.ai/code/session_01UJ23Rb1c5UtxHTfAke9ENQ

mpasternak and others added 2 commits October 24, 2026 20:10
- trasy /test_403/, /test_500/, /test_exception/ tylko dla superużytkownika,
- rozszerzona lista ROLLBAR_SCRUB_FIELDS (tokeny sesji/CSRF/PBN, sekrety
  integracji Uczelni),
- reset hasła: atomowe liczniki (cache.add + cache.incr), dodatkowy limit
  per adres e-mail, formularz nie informuje o istnieniu konta,
- secret_key_guard odrzuca wartość build-ową poza krokiem buildu
  (DJANGO_BPP_BUILD_STAGE=1 inline w RUN collectstatic),
- ewaluacja_dwudyscyplinowcy: uprawnienia jak w ewaluacja_optymalizacja,
- stan_systemu: poprawna nazwa grupy (GR_WPROWADZANIE_DANYCH),
- dane wykresów w szczegółach metryk przez filtr jsonify,
- COinS: kodowanie rft.language; rodzaj_autora_label przez format_html,
- rekord_short w adminie: safe_tytul_html + Truncator(html=True),
- usunięty nieużywany kod (formatted_komunikat, pbn_api.admin.helpers),
- odpięte trasy zakładek menu admin_tools (dashboard bez zmian),
- nagłówek Content-Security-Policy, domyślnie w trybie Report-Only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UJ23Rb1c5UtxHTfAke9ENQ
@mpasternak
mpasternak force-pushed the sec/drobne-hardening branch from 715ec35 to 50c7df7 Compare October 24, 2026 18:17
@mpasternak
mpasternak merged commit 7ea96ff into dev Oct 24, 2026
24 checks passed
@mpasternak
mpasternak deleted the sec/drobne-hardening branch October 24, 2026 18:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant