Przejdź do treści
INDEKS ANALIZ BREACHROAD / NOTA TECHNICZNA

Content Security Policy — wdrożenie CSP krok po kroku

Content Security Policy ogranicza skutki XSS. Zobacz, jak wdrożyć CSP Report-Only, nonce, strict-dynamic, raportowanie i politykę produkcyjną.

MATERIAŁ PUBLICZNY
AUTOR
/ Pentester (OSCP, PNPT)
PUBLIKACJA
9 lipca 2026
CZAS CZYTANIA
11 min czytania
TEMAT
AppSec
Content Security Policy — wdrożenie CSP krok po kroku

Content Security Policy (CSP) pozwala przeglądarce ograniczyć, skąd strona ładuje i wykonuje skrypty, style, ramki oraz inne zasoby. Dobrze wdrożona polityka zmniejsza skutek części podatności XSS, lecz zgodnie ze specyfikacją W3C CSP Level 3 pozostaje warstwą defense in depth — nie zastępuje kodowania wyjścia i bezpiecznej obsługi danych.

Najczęstszy błąd to skopiowanie restrykcyjnego nagłówka na produkcję albo przeciwnie: polityka z unsafe-inline i szerokimi wildcardami, która wygląda dobrze w skanerze, ale niewiele blokuje.

Zacznij od Content-Security-Policy-Report-Only

Tryb Report-Only obserwuje naruszenia bez blokowania zasobów. Włącz go na reprezentatywnym ruchu i zbieraj raporty przez kilka tygodni. Odseparuj realne zależności od rozszerzeń przeglądarki, skanerów i szumu.

Przykładowy punkt startu:

Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'; report-to csp-endpoint

default-src jest fallbackiem, ale ważne dyrektywy definiuj jawnie. object-src 'none' wyłącza stare pluginy, base-uri ogranicza zmianę bazowego URL, a frame-ancestors chroni przed osadzeniem strony.

Nonce zamiast unsafe-inline

Serwer generuje losowy nonce dla każdej odpowiedzi i dodaje go do nagłówka oraz zaufanych tagów <script>. Przeglądarka uruchomi tylko skrypty z właściwą wartością.

Content-Security-Policy: script-src 'nonce-RANDOM' 'strict-dynamic'; object-src 'none'; base-uri 'none'

Nonce musi być nieprzewidywalny, jednorazowy i tworzony po stronie serwera. Nie może pochodzić ze stałej konfiguracji ani być cachowany między użytkownikami. Szablon nie powinien dodawać nonce do treści kontrolowanej przez użytkownika.

strict-dynamic pozwala zaufanemu skryptowi ładować kolejne skrypty bez utrzymywania długiej listy hostów. Wymaga jednak kontroli nad loaderem i testów kompatybilności.

Dyrektywy, które warto ustawić

  • script-src oraz osobno script-src-elem i script-src-attr tam, gdzie potrzebna jest precyzja;
  • style-src, najlepiej bez szerokiego unsafe-inline;
  • img-src, z uwzględnieniem data: tylko gdy jest konieczne;
  • connect-src dla API, WebSocket i telemetryki;
  • frame-src dla dozwolonych osadzeń;
  • frame-ancestors przeciw clickjackingowi;
  • form-action dla miejsc wysyłania formularzy;
  • object-src 'none' i ograniczone base-uri;
  • upgrade-insecure-requests podczas kontrolowanej migracji HTTPS.

Raporty CSP nie są automatycznie podatnościami

Raport zawiera dokument, zablokowaną dyrektywę, źródło i kontekst. Agreguj zdarzenia, usuwaj dane osobowe oraz limituj retencję. Nagły wzrost nowej domeny może oznaczać zmianę aplikacji, wstrzyknięty skrypt albo rozszerzenie użytkownika.

Najważniejsze raporty zamieniaj w testy regresyjne. Pipeline powinien uruchamiać aplikację z polityką i przechodzić krytyczne ścieżki: logowanie, płatność, upload, widgety i analitykę.

Bezpieczna ścieżka wdrożenia

  1. Zinwentaryzuj skrypty, style, ramki, API i zewnętrznych dostawców.
  2. Uruchom Report-Only z ostrożną polityką bazową.
  3. Usuń inline JavaScript i eval, gdzie to możliwe.
  4. Wprowadź nonce lub hashe dla pozostałych skryptów.
  5. Ogranicz źródła do konkretnych protokołów i hostów.
  6. Przetestuj wszystkie role i ścieżki.
  7. Przełącz politykę na tryb egzekwowania etapami.
  8. Utrzymuj endpoint raportowy oraz alarm dla nowych wzorców.

CSP uzupełnia nagłówki bezpieczeństwa HTTP i testy aplikacji, ale nie naprawia źródła XSS. Najpierw koduj dane zgodnie z kontekstem, a polityką ograniczaj skutki błędu.


Nonce, hash i strict-dynamic

Nonce musi być losowy i nowy dla każdej odpowiedzi; nie może być stałą w szablonie ani wartością klienta. Hash pasuje do niezmiennego skryptu inline, ale każda zmiana treści wymaga aktualizacji polityki. strict-dynamic pozwala zaufanemu skryptowi ładować zależności, lecz wymaga przemyślenia modelu bootstrapu i zgodności przeglądarek.

Raporty CSP zawierają adresy i fragmenty kontekstu, więc traktuj je jak dane telemetryczne z retencją i kontrolą dostępu. Grupuj naruszenia według dyrektywy, dokumentu i zablokowanego źródła, odfiltruj szum rozszerzeń, a przed przejściem z Report-Only do enforcement wykonaj testy logowania, płatności i integracji. CSP jest warstwą ograniczającą skutki XSS, nie zamiennikiem kodowania wyjścia.

Źródła: W3C CSP Level 3, OWASP CSP Cheat Sheet, MDN CSP.

UDOSTĘPNIJ / KOPIUJ