Nagłówki bezpieczeństwa HTTP: CSP, HSTS, Permissions-Policy i kompletna konfiguracja Skip to content

Baza wiedzy

Praktyczna wiedza o frontendzie, narzędziach AI i tworzeniu oprogramowania.

Nagłówki bezpieczeństwa HTTP: CSP, HSTS, Permissions-Policy i kompletna konfiguracja

Opublikowano: 16 min czytania Autor: Security

Nagłówki bezpieczeństwa HTTP pozwalają serwerowi przekazać przeglądarce zasady dotyczące ładowania skryptów, osadzania strony, korzystania z kamery i geolokalizacji, przesyłania referrera, interpretowania typów MIME oraz komunikacji przez HTTPS. Dobrze skonfigurowane nagłówki ograniczają skutki części ataków XSS, clickjackingu, MIME confusion, XS-Leaks i niebezpiecznego ładowania zasobów z innych originów.

Nie są jednak magiczną zaporą. Nagłówek nie naprawi błędnej autoryzacji, podatnego API, SQL Injection, wycieku sekretów ani nieaktualnej biblioteki. Jest warstwą defense in depth: zmniejsza powierzchnię ataku i ogranicza to, co przeglądarka może zrobić po wystąpieniu innego błędu.

W 2026 roku najważniejsze jest rozróżnienie trzech grup:

  1. Nagłówki bazowe, które mają sens dla większości stron.
  2. Nagłówki zależne od architektury, które mogą blokować OAuth, płatności, CDN, iframe’y albo pliki PDF, jeśli zostaną dodane bez analizy.
  3. Nagłówki przestarzałe, których nie należy dodawać tylko po to, aby uzyskać wyższy wynik w przypadkowym skanerze.

TL;DR: zacznij od dobrze zaprojektowanego CSP, HSTS po pełnym wdrożeniu HTTPS, X-Content-Type-Options: nosniff, jawnego Referrer-Policy i rozsądnego Permissions-Policy. Ochronę przed osadzaniem realizuj przede wszystkim przez frame-ancestors w CSP, pozostawiając X-Frame-Options jako warstwę kompatybilności. COOP, COEP i CORP wdrażaj dopiero po analizie integracji cross-origin. Wyłącz lub usuń X-XSS-Protection, Expect-CT, HPKP i stary Report-To.

Zalecenia i stan kompatybilności zostały zweryfikowane 23 lipca 2026 roku.

Najważniejsze nagłówki w jednej tabeli

Nagłówek Typowa rekomendacja Co ogranicza Czy wdrażać wszędzie?
Content-Security-Policy polityka dopasowana do aplikacji, najlepiej oparta na nonce lub hashach XSS, injection, nieautoryzowane źródła zasobów, osadzanie tak dla stron renderujących HTML, ale po testach
Strict-Transport-Security max-age=31536000; includeSubDomains, a preload dopiero po analizie downgrade do HTTP, pomijanie błędów certyfikatu tak, gdy cała domena i subdomeny poprawnie działają przez HTTPS
X-Content-Type-Options nosniff MIME sniffing i część MIME confusion tak
Referrer-Policy strict-origin-when-cross-origin lub bardziej restrykcyjna wyciek ścieżek i parametrów URL tak
Permissions-Policy wyłącz nieużywane funkcje, np. camera=(), microphone=(), geolocation=() dostęp dokumentu i iframe’ów do wybranych API zazwyczaj tak, po sprawdzeniu kompatybilności funkcji
CSP frame-ancestors 'none', 'self' albo konkretne originy clickjacking i niechciane osadzanie tak dla dokumentów HTML
X-Frame-Options DENY lub SAMEORIGIN jako kompatybilność clickjacking w starszych implementacjach często, równolegle z frame-ancestors
Cross-Origin-Opener-Policy zwykle same-origin, jeśli aplikacja nie wymaga zachowania relacji z popupami cross-origin część XS-Leaks i dostęp przez window.opener zależnie od OAuth, płatności i popupów
Cross-Origin-Embedder-Policy require-corp lub credentialless tylko świadomie osadzanie cross-origin bez zgody zasobu nie automatycznie
Cross-Origin-Resource-Policy same-origin, same-site albo cross-origin zależnie od zasobu odczyt odpowiedzi przez niepożądane originy zależnie od modelu udostępniania
Cache-Control no-store dla szczególnie wrażliwych odpowiedzi; private dla spersonalizowanych przechowywanie danych w cache dla odpowiedzi wrażliwych
Set-Cookie Secure; HttpOnly; SameSite=Lax/Strict zależnie od procesu kradzież i niewłaściwe wysyłanie cookies dla cookies sesyjnych
Reporting-Endpoints endpoint raportów CSP/COOP/COEP obserwowalność naruszeń polityk opcjonalnie
X-XSS-Protection usunąć albo 0 stary filtr XSS nie włączać
Expect-CT usunąć przestarzały mechanizm CT nie
Public-Key-Pins nie używać historyczny pinning certyfikatów nie

OWASP traktuje nagłówki jako ważne wzmocnienie bezpieczeństwa, ale podkreśla konieczność poprawnej konfiguracji i dopasowania do danego typu odpowiedzi.

Minimalny zestaw dla typowej strony

Poniższy przykład jest punktem startowym, nie konfiguracją do bezrefleksyjnego kopiowania:

Content-Security-Policy: default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'; form-action 'self'; img-src 'self' data: https:; font-src 'self'; style-src 'self'; script-src 'self'; connect-src 'self'; upgrade-insecure-requests
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
X-Frame-Options: DENY

Ta polityka zablokuje:

  • skrypty i style inline,
  • zasoby z nieujętych originów,
  • osadzanie strony w iframe,
  • formularze wysyłane poza własny origin,
  • użycie kamery, mikrofonu i geolokalizacji,
  • ładowanie witryny przez HTTP po zapisaniu HSTS.

Jeżeli strona używa Google Fonts, zewnętrznego API, narzędzia analitycznego, mapy, płatności, logowania OAuth, menedżera tagów albo skryptów inline, politykę trzeba dostosować.

1. Content-Security-Policy: najważniejszy i najtrudniejszy nagłówek

Content-Security-Policy pozwala określić, z jakich źródeł przeglądarka może ładować skrypty, style, obrazy, fonty, ramki i połączenia sieciowe. Dobrze skonfigurowany CSP pomaga ograniczać XSS i ataki polegające na wstrzyknięciu danych, ale nie zastępuje walidacji, kodowania outputu i bezpiecznych API.

Podstawowe dyrektywy

Dyrektywa Rola Typowa wartość startowa
default-src fallback dla nieokreślonych typów zasobów 'self'
script-src dozwolone skrypty nonce lub hashe; ewentualnie 'self'
style-src dozwolone arkusze i style 'self', nonce lub hashe
img-src obrazy 'self' data: https:
font-src fonty 'self' i konkretne CDN
connect-src Fetch, XHR, WebSocket, EventSource własne API i konkretne endpointy
frame-src ramki osadzane przez stronę tylko wymagane originy
frame-ancestors kto może osadzić tę stronę 'none' lub 'self'
form-action dokąd formularze mogą wysyłać dane 'self' lub wskazane endpointy
base-uri dozwolone adresy dla <base> 'self' albo 'none'
object-src pluginy <object> i <embed> 'none'
upgrade-insecure-requests zamiana żądań HTTP na HTTPS bez wartości

Polityka allowlist kontra ścisły CSP

Polityka oparta wyłącznie na listach domen bywa trudna w utrzymaniu. Zaufany CDN może serwować wiele treści, a skrypt third-party może dynamicznie ładować kolejne zależności. web.dev rekomenduje ścisły CSP oparty na nonce albo hashach, a strict-dynamic pozwala ufać skryptom załadowanym przez zaufany skrypt.

Przykład polityki nonce:

Content-Security-Policy:
  default-src 'self';
  base-uri 'self';
  object-src 'none';
  frame-ancestors 'none';
  form-action 'self';
  script-src 'nonce-{RANDOM_NONCE}' 'strict-dynamic';
  style-src 'self' 'nonce-{RANDOM_NONCE}';
  img-src 'self' data: https:;
  font-src 'self';
  connect-src 'self' https://api.example.com;
  upgrade-insecure-requests

W HTML:

<script nonce="{RANDOM_NONCE}">
  window.__APP_CONFIG__ = { apiUrl: "https://api.example.com" };
</script>

Nonce musi być:

  • losowy i trudny do przewidzenia,
  • inny dla każdej odpowiedzi HTML,
  • umieszczony zarówno w nagłówku, jak i zaufanych elementach,
  • generowany po stronie serwera.

Stały nonce wpisany w konfigurację nie daje oczekiwanej ochrony. Jeśli strona jest statyczna i nie może generować nowej wartości dla każdej odpowiedzi, bardziej praktyczny może być CSP oparty na hashach.

unsafe-inline i unsafe-eval

Dodanie 'unsafe-inline' do script-src znacząco osłabia ochronę przed XSS, ponieważ zezwala na wykonywanie kodu inline. 'unsafe-eval' pozwala na mechanizmy wykonujące kod ze stringów, takie jak eval() i konstruktor Function().

Nie usuwaj tych ograniczeń tylko po to, aby uciszyć błędy w konsoli. Najpierw:

  1. przenieś kod inline do plików,
  2. użyj nonce lub hasha,
  3. zidentyfikuj bibliotekę wymagającą eval,
  4. sprawdź, czy można zmienić jej build albo konfigurację.

Trusted Types

Dyrektywa:

Content-Security-Policy: require-trusted-types-for 'script'; trusted-types app-policy

może wymusić przekazywanie typowanych wartości do wybranych DOM XSS sinków, takich jak innerHTML. Od lutego 2026 require-trusted-types-for jest dostępne w aktualnych głównych przeglądarkach, ale starsze wersje mogą go nie obsługiwać.

Trusted Types są rozwiązaniem zaawansowanym. Nie wystarczy dodać nagłówka: aplikacja musi definiować bezpieczne polityki transformacji, a używane frameworki i biblioteki muszą być zgodne.

CSP Report-Only

Najbezpieczniejsze wdrożenie zaczyna się od:

Content-Security-Policy-Report-Only: default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'; report-to csp-endpoint
Reporting-Endpoints: csp-endpoint="https://example.com/security/csp-reports"

Content-Security-Policy-Report-Only raportuje naruszenia bez blokowania zasobów, dzięki czemu można znaleźć brakujące originy przed włączeniem egzekwowania. Reporting-Endpoints zastępuje przestarzały nagłówek Report-To i powinien być preferowany przy deklarowaniu endpointów raportowania.

Raporty CSP mogą zawierać adresy i informacje o zasobach. Endpoint powinien:

  • przyjmować tylko oczekiwane typy i rozmiary danych,
  • mieć rate limiting,
  • nie logować niepotrzebnych danych osobowych,
  • nie renderować otrzymanego payloadu bez kodowania,
  • mieć retencję dopasowaną do celu diagnostycznego.

2. Strict-Transport-Security: HTTPS bez drogi powrotnej

HSTS informuje przeglądarkę, że host powinien być odwiedzany wyłącznie przez HTTPS. Po zapisaniu polityki przeglądarka automatycznie zamienia przyszłe próby HTTP na HTTPS i nie pozwala użytkownikowi ominąć części błędów certyfikatu.

Przykład:

Strict-Transport-Security: max-age=31536000; includeSubDomains

Co oznaczają dyrektywy?

  • max-age=31536000 - zapamiętanie polityki na rok,
  • includeSubDomains - objęcie subdomen,
  • preload - deklaracja chęci umieszczenia domeny na liście preload.

Dlaczego nie zaczynać od dwóch lat i preload?

Błędnie wdrożony HSTS może odciąć legalnych użytkowników. Jeżeli stara subdomena działa tylko po HTTP, certyfikat wygaśnie albo domena korzysta z infrastruktury, której nie kontrolujesz, includeSubDomains i długi max-age mogą spowodować poważną awarię.

Bezpieczniejszy rollout:

5 minut → 1 dzień → 1 tydzień → 1 miesiąc → 1 rok

Na każdym etapie sprawdź:

  • domenę główną,
  • wszystkie aktywne subdomeny,
  • wildcard i SAN w certyfikatach,
  • zasoby legacy,
  • panele, API, pocztę webową i endpointy partnerów.

HSTS preload wymaga między innymi poprawnego certyfikatu, przekierowania HTTP do HTTPS, odpowiedniego max-age, includeSubDomains i dyrektywy preload. Wpis trafia następnie do kodu przeglądarek, a wycofanie może trwać wiele tygodni.

3. X-Content-Type-Options: zatrzymaj zgadywanie MIME

X-Content-Type-Options: nosniff

Nagłówek informuje przeglądarkę, aby respektowała zadeklarowany Content-Type i nie próbowała samodzielnie interpretować odpowiedzi jako innego typu. Dla skryptów i stylów odpowiedź może zostać zablokowana, jeśli MIME nie odpowiada oczekiwanemu typowi.

Nagłówek nie zastępuje poprawnej konfiguracji serwera. Nadal trzeba wysyłać prawidłowe wartości:

Content-Type: text/html; charset=utf-8
Content-Type: text/css; charset=utf-8
Content-Type: application/javascript; charset=utf-8
Content-Type: application/json; charset=utf-8
Content-Type: image/avif

Szczególnie ważne jest to przy:

  • plikach przesyłanych przez użytkowników,
  • endpointach pobierania,
  • zasobach generowanych dynamicznie,
  • storage i CDN,
  • odpowiedziach błędów, które mogą zwracać HTML zamiast oczekiwanego JSON.

4. Referrer-Policy: ogranicz wyciek adresu źródłowego

Referrer-Policy określa, ile informacji z adresu bieżącej strony może zostać przesłane do kolejnego zasobu w nagłówku Referer.

Rozsądny domyślny wariant:

Referrer-Policy: strict-origin-when-cross-origin

Zachowanie:

  • pełny adres przy żądaniach same-origin,
  • tylko origin przy żądaniach cross-origin,
  • brak referrera przy przejściu z HTTPS do HTTP.

Bardziej restrykcyjne opcje:

Referrer-Policy: no-referrer

albo:

Referrer-Policy: same-origin

Wybór zależy od analityki, afiliacji, systemów płatniczych i logiki partnerów. Nie umieszczaj sekretów, tokenów, adresów e-mail ani danych osobowych w URL - nawet najbardziej restrykcyjny Referrer-Policy nie rozwiązuje wszystkich miejsc, w których URL może zostać zapisany.

5. Ochrona przed clickjackingiem: frame-ancestors i X-Frame-Options

Najbardziej elastyczną kontrolę osadzania zapewnia CSP:

Content-Security-Policy: frame-ancestors 'none'

lub:

Content-Security-Policy: frame-ancestors 'self' https://portal.partner.example

frame-ancestors określa, które dokumenty nadrzędne mogą osadzić stronę w <frame>, <iframe>, <object> lub <embed>.

Dla kompatybilności można równolegle dodać:

X-Frame-Options: DENY

albo:

X-Frame-Options: SAMEORIGIN

MDN rekomenduje korzystanie z frame-ancestors, ponieważ daje szersze możliwości niż X-Frame-Options. Wartość ALLOW-FROM jest przestarzała i nowoczesne przeglądarki mogą zignorować cały nagłówek.

X-Frame-Options musi być wysłany jako nagłówek HTTP. Umieszczenie go w <meta http-equiv> nie działa.

6. Permissions-Policy: wyłącz funkcje, których strona nie potrzebuje

Przykład:

Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=()

Nagłówek pozwala kontrolować dostęp dokumentu i osadzonych iframe’ów do funkcji przeglądarki, takich jak kamera, mikrofon, geolokalizacja czy wybrane API urządzenia.

Można zezwolić własnej stronie:

Permissions-Policy: geolocation=(self), camera=(), microphone=()

albo konkretnemu originowi:

Permissions-Policy: geolocation=(self "https://maps.example")

Nie kopiuj długiej listy wszystkich możliwych dyrektyw. Część z nich jest eksperymentalna albo ma różny poziom wsparcia w przeglądarkach. Najpierw określ, które funkcje rzeczywiście wykorzystuje aplikacja, a następnie wyłącz pozostałe istotne możliwości.

7. COOP, COEP i CORP: izolacja cross-origin, ale nie dla każdej strony

Te trzy nagłówki często pojawiają się razem, lecz rozwiązują różne problemy.

Cross-Origin-Opener-Policy

Cross-Origin-Opener-Policy: same-origin

COOP kontroluje, czy nowy dokument otwarty przez window.open() lub nawigację może znajdować się w tej samej grupie kontekstów przeglądania. same-origin rozdziela dokument od cross-origin openerów i pomaga ograniczać klasę ataków XS-Leaks.

Może jednak przerwać:

  • logowanie OAuth przez popup,
  • płatności otwierane w nowym oknie,
  • integracje, które oczekują dostępu do window.opener,
  • komunikację z zaufanym popupem.

Dla niektórych takich procesów właściwsze może być:

Cross-Origin-Opener-Policy: same-origin-allow-popups

Cross-Origin-Embedder-Policy

Cross-Origin-Embedder-Policy: require-corp

COEP wymaga, aby zasoby cross-origin ładowane w trybie no-cors jawnie zezwalały na osadzenie przez CORP albo były pobierane w trybie CORS. Brak odpowiedniego nagłówka może zablokować obrazy, fonty, skrypty, iframe’y i inne zasoby third-party.

Alternatywa:

Cross-Origin-Embedder-Policy: credentialless

pozwala na część żądań no-cors bez jawnego CORP, ale usuwa credentials, w tym cookies.

Cross-Origin-Resource-Policy

Cross-Origin-Resource-Policy: same-origin

CORP określa, które originy mogą odczytać odpowiedź zasobu w żądaniach no-cors:

  • same-origin,
  • same-site,
  • cross-origin.

To polityka konkretnego zasobu, a nie całej komunikacji CORS. MDN ostrzega również o problemie z renderowaniem części plików PDF w Chrome przy niektórych zastosowaniach CORP, dlatego nagłówka nie należy dodawać globalnie bez testów.

Kiedy potrzebna jest cross-origin isolation?

Połączenie:

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

jest wymagane do cross-origin isolation używanego przez wybrane zaawansowane API, między innymi pełny dostęp do SharedArrayBuffer. Nie wdrażaj go jednak tylko w celu zdobycia dodatkowego punktu w skanerze. Najpierw zinwentaryzuj wszystkie zewnętrzne zasoby i procesy popup.

8. Bezpieczne cookies i Cache-Control

Choć Set-Cookie i Cache-Control nie zawsze są klasyfikowane jako „security headers”, ich konfiguracja ma bezpośredni wpływ na ochronę sesji i danych.

Cookie sesyjne

Set-Cookie: __Host-session=RANDOM_VALUE; Path=/; Secure; HttpOnly; SameSite=Lax
  • Secure ogranicza wysyłanie cookie do HTTPS,
  • HttpOnly blokuje odczyt przez JavaScript,
  • SameSite ogranicza przesyłanie w żądaniach cross-site,
  • prefiks __Host- wymaga Secure, Path=/ i braku atrybutu Domain, dzięki czemu cookie jest silniej związane z hostem.

SameSite=Strict jest bezpieczniejsze, ale może utrudniać powrót z logowania, płatności lub linków cross-site. SameSite=None wymaga Secure i powinno być używane tylko wtedy, gdy cookie naprawdę musi działać w kontekście cross-site.

Odpowiedzi wrażliwe

Cache-Control: no-store

no-store informuje cache prywatne i współdzielone, aby nie przechowywały odpowiedzi. Dla spersonalizowanych treści, które mogą być przechowywane w przeglądarce, ale nie w cache współdzielonym, odpowiednie może być:

Cache-Control: private, no-cache

MDN zaleca jawne private dla spersonalizowanych odpowiedzi, ponieważ brak właściwej polityki może doprowadzić do zapisania treści w cache współdzielonym.

9. Usuń informacje o stosie technologicznym

Nagłówki takie jak:

Server: nginx/1.24.0
X-Powered-By: PHP/8.4
X-AspNet-Version: 4.0.30319

ułatwiają fingerprinting. Ich usunięcie nie ukryje technologii przed zdeterminowanym atakującym, ale eliminuje bezpośrednie ujawnianie wersji.

Dobra praktyka:

  • usuń X-Powered-By,
  • wyłącz nagłówki wersji frameworka,
  • ogranicz szczegółowość Server,
  • nie dodawaj fałszywej, wprowadzającej w błąd wersji,
  • nie zakładaj, że samo ukrycie nagłówka naprawia podatności.

OWASP zaleca usuwanie X-Powered-By i nieinformacyjne wartości Server, podkreślając jednocześnie, że stos można rozpoznać innymi metodami.

10. Nagłówki przestarzałe i błędne zalecenia

X-XSS-Protection

Nie włączaj:

X-XSS-Protection: 1; mode=block

OWASP ostrzega, że stary filtr XSS może w niektórych sytuacjach tworzyć podatności w bezpiecznej stronie. Rekomendacja to brak nagłówka lub jawne wyłączenie:

X-XSS-Protection: 0

Ochronę należy budować przez CSP, kodowanie outputu i bezpieczne API.

Expect-CT

Expect-CT jest w praktyce przestarzały, ponieważ nowoczesne klienty wymagają Certificate Transparency dla aktualnych certyfikatów. MDN określa go jako w większości obsolete od czerwca 2021 roku.

Public-Key-Pins

HPKP nie powinien być wdrażany. Błędny pin mógł długotrwale odciąć domenę od użytkowników, a mechanizm został usunięty z nowoczesnych przeglądarek. Korzystaj z poprawnego TLS, automatycznego odnawiania, CAA, monitoringu certyfikatów i ewentualnie HSTS preload po analizie.

Report-To

Stary nagłówek:

Report-To: { ... }

jest przestarzały. Do deklarowania endpointów należy używać:

Reporting-Endpoints: csp="https://example.com/reports/csp"

Access-Control-Allow-Origin: * jako „nagłówek bezpieczeństwa”

CORS nie jest zestawem nagłówków, które należy dodawać globalnie. Access-Control-Allow-Origin rozluźnia Same-Origin Policy dla wskazanych żądań. Dla API z credentials nie można łączyć wildcard * z dostępem uwierzytelnionym. Zezwalaj wyłącznie wymaganym originom i waliduj je po stronie serwera.

11. Przykładowe konfiguracje serwera

Nginx

add_header Content-Security-Policy "default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'; form-action 'self'; img-src 'self' data: https:; style-src 'self'; script-src 'self'; connect-src 'self'; upgrade-insecure-requests" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header X-Frame-Options "DENY" always;

Opcja always jest ważna, aby nagłówki pojawiały się również dla odpowiedzi błędów i innych kodów, nie tylko wybranych odpowiedzi 2xx/3xx.

Apache

<IfModule mod_headers.c>
  Header always set Content-Security-Policy "default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'; form-action 'self'; img-src 'self' data: https:; style-src 'self'; script-src 'self'; connect-src 'self'; upgrade-insecure-requests"
  Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
  Header always set X-Content-Type-Options "nosniff"
  Header always set Referrer-Policy "strict-origin-when-cross-origin"
  Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
  Header always set X-Frame-Options "DENY"
</IfModule>

PHP

<?php

header("Content-Security-Policy: default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'; form-action 'self'; img-src 'self' data: https:; style-src 'self'; script-src 'self'; connect-src 'self'; upgrade-insecure-requests");
header("Strict-Transport-Security: max-age=31536000; includeSubDomains");
header("X-Content-Type-Options: nosniff");
header("Referrer-Policy: strict-origin-when-cross-origin");
header("Permissions-Policy: camera=(), microphone=(), geolocation=()");
header("X-Frame-Options: DENY");

Nagłówki muszą zostać wysłane przed treścią odpowiedzi. Dla nonce generuj kryptograficznie losową wartość osobno dla każdego requestu.

Node.js / Express bez zależności

app.use((req, res, next) => {
  res.setHeader(
    "Content-Security-Policy",
    "default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'; form-action 'self'; img-src 'self' data: https:; style-src 'self'; script-src 'self'; connect-src 'self'; upgrade-insecure-requests"
  );
  res.setHeader(
    "Strict-Transport-Security",
    "max-age=31536000; includeSubDomains"
  );
  res.setHeader("X-Content-Type-Options", "nosniff");
  res.setHeader("Referrer-Policy", "strict-origin-when-cross-origin");
  res.setHeader(
    "Permissions-Policy",
    "camera=(), microphone=(), geolocation=()"
  );
  res.setHeader("X-Frame-Options", "DENY");
  res.removeHeader("X-Powered-By");
  next();
});

W aplikacji korzystającej z CDN, WebSocketów, map, płatności albo OAuth powyższy CSP trzeba rozszerzyć. Nie dodawaj 'unsafe-inline' tylko dlatego, że pierwszy test zakończył się błędami.

12. Jak wdrażać bez awarii?

Etap 1: inwentaryzacja

Spisz:

  • wszystkie domeny skryptów, stylów, fontów i obrazów,
  • endpointy API i WebSocket,
  • iframe’y,
  • popupy OAuth i płatności,
  • zasoby na CDN,
  • pliki przesyłane przez użytkowników,
  • subdomeny objęte przyszłym HSTS,
  • funkcje przeglądarki, których aplikacja rzeczywiście używa.

Etap 2: obserwacja

  • uruchom CSP w Report-Only,
  • zbieraj raporty i błędy konsoli,
  • testuj wszystkie krytyczne ścieżki,
  • testuj mobile i przeglądarki używane przez klientów,
  • sprawdź odpowiedzi błędów, redirecty i pliki statyczne.

Etap 3: stopniowe egzekwowanie

  • najpierw object-src, base-uri, frame-ancestors i form-action,
  • następnie zasoby statyczne,
  • na końcu ścisłe script-src,
  • rollout HSTS zaczynaj od krótkiego max-age,
  • COOP/COEP testuj osobno na integracjach popup i cross-origin.

Etap 4: monitoring regresji

Dodaj testy w CI, które:

  • pobierają reprezentatywne URL,
  • weryfikują brak duplikatów nagłówków,
  • sprawdzają zgodność wartości,
  • wykrywają przypadkowe usunięcie CSP/HSTS,
  • potwierdzają poprawne MIME types,
  • wykonują test end-to-end logowania i płatności.

13. Jak testować nagłówki?

Najpierw sprawdź odpowiedź bezpośrednio:

curl -I https://example.com/

Dla redirectu i końcowej odpowiedzi:

curl -IL https://example.com/

Dla konkretnego zasobu:

curl -I https://example.com/assets/app.js

Sprawdź:

  • czy nagłówki są obecne na stronie głównej, logowaniu, 404 i 500,
  • czy CSP nie jest wysłany wielokrotnie z konfliktującymi wartościami,
  • czy HSTS pochodzi wyłącznie z odpowiedzi HTTPS,
  • czy Content-Type odpowiada rzeczywistej treści,
  • czy CDN lub proxy nie usuwa nagłówków,
  • czy nagłówki nie występują wyłącznie na homepage.

Możesz również użyć bezpłatnego Inspektora nagłówków bezpieczeństwa POLPROG, który sprawdza między innymi HSTS, CSP i ochronę przed osadzaniem. Certyfikat oraz DNS sprawdzisz w Inspektorze DNS i SSL, a szerszą analizę SEO, wydajności, dostępności i bezpieczeństwa wykonasz przez Kondycję witryny.

Checklista wdrożenia

CSP

  • default-src ma restrykcyjną wartość.
  • object-src 'none'.
  • base-uri jest ograniczone.
  • frame-ancestors odpowiada rzeczywistemu modelowi osadzania.
  • form-action ogranicza cele formularzy.
  • Skrypty wykorzystują nonce lub hashe, jeśli aplikacja wymaga inline.
  • Nonce jest losowy dla każdej odpowiedzi.
  • Nie ma nieuzasadnionego 'unsafe-inline'.
  • Nie ma nieuzasadnionego 'unsafe-eval'.
  • CSP został najpierw przetestowany w Report-Only.
  • Raporty mają rate limiting i ograniczoną retencję.

HTTPS i HSTS

  • Wszystkie strony i zasoby działają przez HTTPS.
  • HTTP przekierowuje bezpośrednio do HTTPS.
  • Certyfikat jest monitorowany.
  • Wszystkie subdomeny zostały zinwentaryzowane.
  • max-age zwiększano etapami.
  • includeSubDomains jest bezpieczne dla całej domeny.
  • preload został dodany dopiero po analizie konsekwencji.

Pozostałe nagłówki

  • X-Content-Type-Options: nosniff.
  • Wszystkie odpowiedzi mają właściwy Content-Type.
  • Referrer-Policy jest ustawiony jawnie.
  • Permissions-Policy wyłącza nieużywane funkcje.
  • X-Frame-Options nie używa ALLOW-FROM.
  • COOP nie psuje OAuth i płatności.
  • COEP nie blokuje zasobów third-party.
  • CORP jest dopasowany do konkretnego rodzaju zasobu.
  • Cookies sesyjne mają Secure, HttpOnly i właściwe SameSite.
  • Wrażliwe odpowiedzi mają właściwy Cache-Control.
  • X-Powered-By i wersje frameworków są usunięte.
  • X-XSS-Protection jest wyłączony albo nieobecny.
  • Expect-CT, HPKP i stary Report-To zostały usunięte.

Werdykt

Dla większości stron firmowych i aplikacji właściwa kolejność jest następująca:

  1. Poprawne HTTPS, typy MIME i bezpieczne cookies.
  2. CSP dopasowany do aplikacji i wdrażany przez Report-Only.
  3. HSTS wdrażany etapami.
  4. nosniff, Referrer-Policy, Permissions-Policy i ochrona przed framingiem.
  5. COOP, COEP i CORP tylko wtedy, gdy model cross-origin jest dobrze zrozumiany.
  6. Usunięcie przestarzałych oraz informacyjnych nagłówków.

Najlepszy zestaw nagłówków nie jest najdłuższym zestawem. Jest najmniejszą polityką, która rzeczywiście odpowiada architekturze aplikacji, została przetestowana na krytycznych ścieżkach i jest monitorowana po każdym wdrożeniu.

HTTP Headers Security CSP HSTS Web Security

Najczęściej zadawane pytania

Czy nagłówki bezpieczeństwa chronią przed wszystkimi atakami?

Nie. Ograniczają wybrane zachowania przeglądarki i skutki części podatności, ale nie zastępują autoryzacji, walidacji, aktualizacji zależności, bezpiecznego przechowywania sekretów ani testów bezpieczeństwa.

Jaki nagłówek jest najważniejszy?

Dla stron HTML największy potencjał ma dobrze wdrożony CSP. Jest jednak również najłatwiejszy do błędnej konfiguracji, dlatego należy zacząć od trybu Report-Only.

Czy można skopiować gotowy CSP?

Można wykorzystać go jako punkt startowy, ale polityka musi odzwierciedlać faktyczne skrypty, API, fonty, iframe’y, formularze i integracje konkretnej aplikacji.

Czy X-Frame-Options jest nadal potrzebny?

frame-ancestors w CSP jest nowocześniejszym i elastyczniejszym rozwiązaniem. X-Frame-Options: DENY lub SAMEORIGIN może pozostać jako warstwa kompatybilności. Nie używaj ALLOW-FROM.

Czy HSTS można od razu ustawić na dwa lata?

Technicznie tak, ale jest to ryzykowne przed weryfikacją wszystkich subdomen, certyfikatów i usług legacy. Bezpieczniej zwiększać max-age stopniowo.

Czy warto użyć HSTS preload?

Tak tylko wtedy, gdy cała domena i wszystkie subdomeny są trwale gotowe na HTTPS. Preload jest trudniejszy do wycofania niż zwykły nagłówek zapisany w cache przeglądarki.

Czy Permissions-Policy działa we wszystkich przeglądarkach identycznie?

Nie. Sam nagłówek i poszczególne dyrektywy mają różny poziom wsparcia, a część funkcji jest eksperymentalna. Testuj dokładnie te dyrektywy, których używasz.

Czy powinienem włączyć COEP i CORP na całej stronie?

Nie automatycznie. Mogą blokować zasoby third-party, fonty, obrazy, iframe’y i pliki PDF. Najpierw zinwentaryzuj zasoby cross-origin oraz sprawdź ich CORS i CORP.

Dlaczego skaner obniża ocenę za brak X-XSS-Protection?

Niektóre skanery stosują przestarzałe reguły. Aktualne zalecenie OWASP to nie ustawiać tego nagłówka albo wyłączyć filtr wartością 0.

Czy CSP może zepsuć stronę?

Tak. Zbyt restrykcyjny CSP może zablokować skrypty, style, fonty, API i płatności. Dlatego wdrożenie należy zaczynać od Content-Security-Policy-Report-Only.

Czy nagłówki powinny być wysyłane na stronach błędów?

Tak, o ile mają znaczenie dla danego typu odpowiedzi. Szczególnie istotne jest, aby strony błędów renderujące HTML nie traciły CSP, nosniff, Referrer-Policy ani ochrony przed framingiem.

Źródła i przypisy

  1. OWASP Cheat Sheet Series, HTTP Security Response Headersmateriał uzupełniający
  2. MDN Web Docs, Content Security Policymateriał uzupełniający
  3. web.dev, Mitigate cross-site scripting with a strict Content Security Policymateriał uzupełniający
  4. MDN Web Docs, CSP require-trusted-types-formateriał uzupełniający
  5. MDN Web Docs, Content-Security-Policy-Report-Onlymateriał uzupełniający
  6. MDN Web Docs, Reporting-Endpointsmateriał uzupełniający
  7. MDN Web Docs, Strict-Transport-Securitymateriał uzupełniający
  8. OWASP Cheat Sheet Series, HTTP Strict Transport Securitymateriał uzupełniający
  9. HSTS Preload, Submission Requirementsmateriał uzupełniający
  10. MDN Web Docs, X-Content-Type-Optionsmateriał uzupełniający
  11. MDN Web Docs, Referrer-Policymateriał uzupełniający
  12. MDN Web Docs, CSP frame-ancestorsmateriał uzupełniający
  13. MDN Web Docs, X-Frame-Optionsmateriał uzupełniający
  14. MDN Web Docs, Permissions-Policymateriał uzupełniający
  15. MDN Web Docs, Cross-Origin-Opener-Policymateriał uzupełniający
  16. MDN Web Docs, Cross-Origin-Embedder-Policymateriał uzupełniający
  17. MDN Web Docs, Cross-Origin Resource Policymateriał uzupełniający
  18. MDN Web Docs, Set-Cookiemateriał uzupełniający
  19. MDN Web Docs, Cache-Controlmateriał uzupełniający
  20. MDN Web Docs, Expect-CTmateriał uzupełniający
  21. POLPROG, Inspektor nagłówków bezpieczeństwamateriał uzupełniający

Czy ten artykuł był pomocny?

Nowe artykuły na e-mail

Jeden krótki e-mail przy każdym nowym artykule. Bez spamu, wypisujesz się jednym kliknięciem.

Wykorzystujemy e-mail wyłącznie do wysyłki nowych artykułów. Bez udostępniania stronom trzecim.

Wróć do bazy wiedzy