Skip to content

Nagłówki bezpieczeństwa HTTP

Nagłówki bezpieczeństwa to dyrektywy wysyłane przez serwer w odpowiedzi HTTP, które instruują przeglądarkę jak ma się zachowywać w określonych sytuacjach: skąd może ładować zasoby, czy zezwalać na osadzanie strony w ramkach, jak długo wymuszać HTTPS. Działają po stronie klienta — serwer deklaruje zasady, przeglądarka je egzekwuje.

Poprawnie skonfigurowane nagłówki ograniczają skutki ataków XSS, clickjackingu, przechwytywania sesji i wycieków informacji o infrastrukturze. Nie zastępują bezpiecznego kodu, ale stanowią dodatkową warstwę ochrony niezależną od aplikacji.

Omawiane nagłówki

NagłówekCel
Content-Security-PolicyKontrola źródeł zasobów, ochrona przed XSS
Strict-Transport-SecurityWymuszenie HTTPS
X-Content-Type-OptionsBlokada MIME-sniffingu
X-Frame-OptionsOchrona przed clickjackingiem
Permissions-PolicyKontrola dostępu do funkcji przeglądarki
Referrer-PolicyKontrola danych przesyłanych w nagłówku Referer
Access-Control-Allow-OriginZasady współdzielenia zasobów między domenami (CORS)

Content-Security-Policy

Content-Security-Policy (CSP) to jeden z najważniejszych nagłówków bezpieczeństwa. Pozwala określić, skąd przeglądarka może ładować skrypty, style, obrazy, fonty i inne zasoby. Jeżeli zasób pochodzi ze źródła, którego nie ma na liście, przeglądarka go blokuje — nawet jeśli atakujący zdołał wstrzyknąć złośliwy kod do strony.

Podstawowe dyrektywy

  • default-src — domyślne źródła dla wszystkich typów zasobów, których nie obejmują bardziej szczegółowe dyrektywy
  • script-src — źródła skryptów JavaScript
  • style-src — źródła arkuszy CSS
  • img-src — źródła obrazów
  • font-src — źródła fontów
  • connect-src — dozwolone połączenia (fetch, XHR, WebSocket)
  • frame-src — źródła dla elementów <iframe>
  • frame-ancestors — określa, które domeny mogą osadzać twoją stronę w ramce (zastępuje X-Frame-Options)
  • object-src — źródła dla <object>, <embed>, <applet>

Słowa kluczowe

  • 'self' — tylko bieżąca domena
  • 'none' — blokuje wszystkie źródła
  • 'unsafe-inline' — zezwala na kod inline (skrypty i style wbudowane w HTML) — używaj tylko gdy niezbędne
  • 'unsafe-eval' — zezwala na eval() i podobne funkcje — unikaj jeśli możliwe

Przykłady

Zezwolenie na zasoby tylko z własnej domeny i zaufanych CDN:

apache
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' https://fonts.gstatic.com;

Blokada osadzania strony w ramkach przez inne domeny:

apache
Content-Security-Policy: frame-ancestors 'self';

Raportowanie naruszeń bez blokowania (tryb testowy):

apache
Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-raport;

💡 Zacznij od trybu Report-Only

CSP jest trudny do skonfigurowania na działającej stronie — zbyt restrykcyjne ustawienia mogą zepsuć funkcjonalność. Użyj nagłówka Content-Security-Policy-Report-Only i przez kilka dni obserwuj raporty naruszeń zanim włączysz blokowanie.


Strict-Transport-Security

Strict-Transport-Security (HSTS) instruuje przeglądarkę, żeby przez określony czas łączyła się z twoją stroną wyłącznie przez HTTPS — nawet jeśli użytkownik wpisze adres z http://. Eliminuje możliwość przypadkowego niezaszyfrowanego połączenia i utrudnia ataki man-in-the-middle.

Parametry

  • max-age=<sekundy> — przez ile sekund przeglądarka ma pamiętać o wymuszeniu HTTPS. 31536000 to jeden rok.
  • includeSubDomains — rozszerza politykę na wszystkie subdomeny twojej domeny
  • preload — zgłasza domenę do wbudowanej listy HSTS przeglądarek (wymaga spełnienia wymagań i osobnej rejestracji na hstspreload.org)

Przykład

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

⚠️ Przed włączeniem HSTS

Upewnij się, że twoja strona w pełni działa przez HTTPS — wszystkie zasoby, subdomeny, przekierowania. HSTS z includeSubDomains obejmie każdą subdomenę, w tym te, które mogą nie mieć certyfikatu SSL. Błędna konfiguracja może zablokować dostęp do strony na czas określony w max-age.


X-Content-Type-Options

Zapobiega tzw. MIME-sniffingowi — sytuacji, w której przeglądarka próbuje samodzielnie zgadnąć typ zawartości pliku na podstawie jego treści, ignorując nagłówek Content-Type. Atakujący mogą wykorzystać to zachowanie, serwując złośliwy skrypt udający obraz.

Jedyna sensowna wartość to nosniff:

apache
X-Content-Type-Options: nosniff

Po ustawieniu tego nagłówka przeglądarka zawsze respektuje Content-Type zadeklarowany przez serwer, bez zgadywania.


X-Frame-Options

Kontroluje, czy twoja strona może być osadzana w elementach <iframe>, <frame> lub <object> na innych domenach. Chroni przed clickjackingiem — techniką, gdzie atakujący nakłada niewidoczną warstwę twojej strony na inną, skłaniając użytkownika do kliknięcia nieświadomie.

Wartości

  • DENY — całkowity zakaz osadzania strony w ramkach
  • SAMEORIGIN — osadzanie dozwolone tylko przez tę samą domenę
apache
X-Frame-Options: SAMEORIGIN

INFO

X-Frame-Options jest nadal powszechnie obsługiwany, jednak nowocześniejszym odpowiednikiem jest dyrektywa frame-ancestors w nagłówku Content-Security-Policy. Daje więcej możliwości (np. zezwolenie konkretnej domenie zewnętrznej) i jest preferowana przez aktualne standardy. Oba nagłówki możesz ustawiać jednocześnie dla kompatybilności ze starszymi przeglądarkami.


Permissions-Policy

Permissions-Policy pozwala kontrolować dostęp do funkcji przeglądarki — geolokalizacji, kamery, mikrofonu, autoodtwarzania i innych — zarówno dla twojej strony, jak i dla osadzonych ramek iframe.

Składnia

apache
Permissions-Policy: geolocation=(), camera=(), microphone=(), autoplay=(self)
  • () — całkowity zakaz, nawet dla twojej strony
  • (self) — dostęp tylko dla twojej domeny
  • (self "https://partner.example.com") — dostęp dla twojej domeny i wskazanego partnera

Przykład dla typowej strony

apache
Permissions-Policy: accelerometer=(), autoplay=(self), camera=(), geolocation=(), gyroscope=(), microphone=(), payment=(), picture-in-picture=(self), usb=()

INFO

Feature-Policy to poprzednia nazwa tego nagłówka, używana przed 2020 rokiem. Przeglądarki w dużej mierze go zignorują lub obsłużą z ostrzeżeniami. Jeżeli gdzieś widzisz Feature-Policy — zastąp go Permissions-Policy.


Referrer-Policy

Kontroluje, jakie informacje o poprzedniej stronie (nagłówek Referer) przeglądarka przekazuje przy nawigacji i żądaniach do zasobów zewnętrznych. Bez tego nagłówka przeglądarka może wysyłać pełny URL — łącznie z parametrami zapytania, tokenami w URL czy ścieżkami do wewnętrznych podstron.

Główne wartości

WartośćZachowanie
no-referrerReferer nigdy nie jest wysyłany
strict-originWysyła tylko domenę, tylko przy HTTPS→HTTPS
strict-origin-when-cross-originPełny URL dla tej samej domeny, tylko domena dla cross-origin
no-referrer-when-downgradePełny URL przy HTTPS→HTTPS, nic przy HTTPS→HTTP
unsafe-urlZawsze pełny URL — unikaj

Dobry kompromis między bezpieczeństwem a użytecznością analityczną:

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

💡 Dlaczego to ważne?

Jeżeli twoja strona ma w URL tokeny resetowania haseł, identyfikatory sesji lub wewnętrzne ścieżki — bez Referrer-Policy te wartości mogą wyciec do zewnętrznych serwisów (np. przez załadowanie zewnętrznego skryptu analitycznego).


Access-Control-Allow-Origin

Nagłówek związany z mechanizmem CORS (Cross-Origin Resource Sharing). Określa, które domeny mogą pobierać zasoby z twojego serwera przez żądania cross-origin (np. JavaScript z innej domeny wywołujący twoje API).

Wartości

  • * — każda domena może pobierać zasoby (stosuj tylko dla publicznych API bez uwierzytelnienia)
  • https://zaufana-domena.pl — dostęp tylko dla wskazanej domeny
apache
Access-Control-Allow-Origin: https://aplikacja.twojadomena.pl

⚠️ Wildcard i ciasteczka

Access-Control-Allow-Origin: * nie działa razem z Access-Control-Allow-Credentials: true. Jeżeli twoje API używa ciasteczek do uwierzytelnienia, musisz podać konkretną domenę zamiast *.

INFO

Access-Control-Allow-Origin jest nagłówkiem odpowiedzi dla zasobów udostępnianych innym serwisom, a nie mechanizmem ochrony twojej strony przed zewnętrznymi żądaniami. Nie zastępuje uwierzytelnienia ani walidacji po stronie serwera.


Jak sprawdzić aktualne nagłówki

Najszybciej przez securityheaders.com — wpisz adres swojej strony i otrzymasz ocenę A–F z listą brakujących i niepoprawnych nagłówków.

Alternatywnie przez terminal:

bash
curl -I https://twojadomena.pl

Aby wyfiltrować tylko nagłówki bezpieczeństwa:

bash
curl -sI https://twojadomena.pl | grep -iE "content-security|strict-transport|x-content|x-frame|permissions|referrer"

Wdrożenie przez .htaccess

Na hostingu Joton (LiteSpeed) i klasycznym Apache nagłówki ustawia się w pliku .htaccess w katalogu głównym strony. Plik możesz edytować przez Menedżer plików w panelu Joton lub przez FTP/SSH.

apache
<IfModule mod_headers.c>
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-Permitted-Cross-Domain-Policies "none"
    Header always unset X-Powered-By
    Header always unset Server
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" env=HTTPS
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    Header always set Permissions-Policy "accelerometer=(), autoplay=(self), camera=(), encrypted-media=(self), fullscreen=(self), geolocation=(self), microphone=(), midi=(), payment=(), picture-in-picture=(self)"
    Header always set Content-Security-Policy "default-src 'self'; object-src 'none'; script-src 'self' https: data: blob: 'unsafe-inline' 'unsafe-eval'; connect-src 'self' https:; style-src 'self' https: 'unsafe-inline'; font-src 'self' data: https:; img-src 'self' blob: data: https:; frame-src 'self' https: blob:; frame-ancestors 'self';"
</IfModule>
apache
<IfModule mod_headers.c>
    Header set X-Frame-Options "SAMEORIGIN"
    Header set X-Content-Type-Options "nosniff"
    Header set X-Permitted-Cross-Domain-Policies "none"
    Header set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
    Header set Referrer-Policy "strict-origin-when-cross-origin"
    Header set Permissions-Policy "accelerometer=(), autoplay=(self), camera=(), geolocation=(self), microphone=(), payment=()"
    Header set Content-Security-Policy "upgrade-insecure-requests; default-src 'self'; script-src 'self' https: 'unsafe-inline'; style-src 'self' https: 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' https: data:;"
    Header always unset X-Powered-By
    Header unset X-Powered-By
</IfModule>

💡 Header set vs Header always set

Header always set ustawia nagłówek we wszystkich odpowiedziach serwera — łącznie z błędami (404, 500). Header set działa tylko przy odpowiedziach 2xx. Na LiteSpeed użyj always aby nagłówki były obecne nawet na stronach błędów.


Uwagi i niepożądane skutki

Nagłówki bezpieczeństwa mogą powodować problemy jeśli są zbyt restrykcyjne:

  • CSP i zewnętrzne skrypty — zbyt wąskie script-src zablokuje skrypty analityczne, chat widgety, mapy Google. Przed wdrożeniem sprawdź przez Content-Security-Policy-Report-Only.
  • HSTS i brakujące certyfikaty — jeśli subdomena nie ma SSL a włączyłeś includeSubDomains, przeglądarka zablokuje do niej dostęp na cały czas max-age.
  • Permissions-Policy i wtyczki WordPress — niektóre wtyczki (np. płatności, reCAPTCHA) wymagają dostępu do funkcji przeglądarki. Zbyt restrykcyjna polityka może je zablokować.

Zawsze testuj nagłówki najpierw na środowisku stagingowym zanim wdrożysz na produkcję.

X-XSS-Protection (przestarzały)

Nagłówek X-XSS-Protection był obsługiwany przez starsze przeglądarki (Internet Explorer, stary Edge, Chrome przed wersją 78) i uruchamiał wbudowany filtr XSS. Współczesne przeglądarki (Chrome 78+, Firefox, nowy Edge) całkowicie go ignorują lub usunęły wsparcie.

Nie wdrażaj go na nowych stronach — w niektórych konfiguracjach mógł paradoksalnie wprowadzać nowe podatności. Zamiast niego używaj Content-Security-Policy.

Jeżeli widzisz go w istniejącej konfiguracji .htaccess, możesz go bezpiecznie usunąć.


Przydatne linki