Nagłówki HTTP bezpieczeństwa to instrukcje które Twój serwer wysyła do przeglądarki razem z każdą odpowiedzią. Przeglądarka stosuje się do tych instrukcji - na przykład odmawiając załadowania skryptu który nie pochodzi z Twojej domeny (CSP) albo wymuszając połączenie HTTPS przez rok (HSTS). Ich brak to jeden z najczęstszych powodów niskich wyników w audytach bezpieczeństwa.
Strict-Transport-Security (HSTS)
HSTS nakazuje przeglądarce używać wyłącznie HTTPS dla Twojej domeny przez określony czas - nawet gdy użytkownik wpisze 'http://'. Chroni przed atakami SSL stripping gdzie atakujący w tej samej sieci WiFi przechwytuje i degraduje połączenie do HTTP.
Wskazówka - Preload oznacza że Twoja domena zostaje wpisana do listy w przeglądarkach (hstspreload.org). Przed dodaniem 'preload' upewnij się że CAŁA domena i wszystkie subdomeny działają na HTTPS - nie możesz tego łatwo cofnąć.
# Podstawowy HSTS (6 miesięcy): Strict-Transport-Security: max-age=15552000 # Zalecany (2 lata + subdomeny): Strict-Transport-Security: max-age=63072000; includeSubDomains # Maksymalna ochrona (2 lata + preload list): Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
Content-Security-Policy (CSP)
CSP to lista źródeł z których przeglądarka może ładować zasoby - skrypty, style, obrazy, fonty. Poprawna polityka CSP jest najskuteczniejszą ochroną przed atakami XSS (Cross-Site Scripting). Bez CSP - jeden wstrzyknięty tag <script> może wykraść dane sesji wszystkich użytkowników.
Wskazówka - CSP z 'unsafe-inline' w script-src neutralizuje ochronę przed XSS. Zamiast tego użyj nonces (jednorazowych tokenów) generowanych server-side dla każdego żądania. Next.js 15+ ma wbudowane wsparcie dla CSP nonces.
# Minimalna CSP dla Next.js (bez inline scripts):
Content-Security-Policy:
default-src 'self';
script-src 'self' 'nonce-{NONCE}';
style-src 'self' 'unsafe-inline';
img-src 'self' data: https:;
font-src 'self';
connect-src 'self' https://api.twojadomena.pl;
frame-ancestors 'none';
# Uproszczona (bez nonces - niższy score):
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:;X-Frame-Options - ochrona przed clickjacking
Clickjacking to atak gdzie atakujący ładuje Twoją stronę w ukrytym iframe i nakłania użytkownika do kliknięcia niewidocznych przycisków - np. 'Zatwierdź przelew'. X-Frame-Options blokuje osadzanie strony w ramce.
Wskazówka - Jeśli używasz CSP z frame-ancestors - X-Frame-Options jest zbędne, ale warto dodać oba dla starszych przeglądarek. frame-ancestors w CSP ma wyższy priorytet w nowoczesnych przeglądarkach.
# Zabroń osadzania w jakimkolwiek iframe: X-Frame-Options: DENY # Zezwól tylko na osadzanie z tej samej domeny: X-Frame-Options: SAMEORIGIN # Nowoczesna alternatywa (przez CSP): Content-Security-Policy: frame-ancestors 'none';
X-Content-Type-Options: nosniff
MIME sniffing to mechanizm gdzie przeglądarka 'zgaduje' typ pliku niezależnie od nagłówka Content-Type. Atakujący może wgrać plik graficzny zawierający JavaScript i sprawić że przeglądarka go wykona. nosniff wyłącza to zachowanie.
X-Content-Type-Options: nosniff
Referrer-Policy - kontrola danych w nagłówku Referer
Gdy użytkownik klika link i przechodzi na inną stronę, przeglądarka domyślnie wysyła pełny URL źródłowy w nagłówku Referer. Może to ujawnić prywatne parametry URL (token resetowania hasła, ID sesji, dane w query string).
# Zalecana konfiguracja: Referrer-Policy: strict-origin-when-cross-origin # Maksymalna prywatność: Referrer-Policy: no-referrer # Wyjaśnienie: # strict-origin-when-cross-origin: # - Same-origin: pełny URL # - Cross-origin: tylko protokół + domena (bez ścieżki) # - Degradacja do no-referrer gdy przejście z HTTPS na HTTP
Permissions-Policy - dostęp do API przeglądarki
Permissions-Policy (dawniej Feature-Policy) kontroluje dostęp do API przeglądarki: kamera, mikrofon, geolokalizacja, fullscreen. Atakujący który wstrzyknął skrypt nie powinien móc aktywować kamery użytkownika.
Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=self
Jak dodać nagłówki w Next.js?
// next.config.ts
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
async headers() {
return [
{
source: '/(.*)',
headers: [
{ key: 'X-Frame-Options', value: 'DENY' },
{ key: 'X-Content-Type-Options', value: 'nosniff' },
{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
{ key: 'Strict-Transport-Security',
value: 'max-age=63072000; includeSubDomains' },
{ key: 'Permissions-Policy',
value: 'camera=(), microphone=(), geolocation=()' },
],
},
];
},
};
export default nextConfig;Jak dodać nagłówki w Nginx?
# /etc/nginx/sites-available/twojadomena.pl
server {
listen 443 ssl;
server_name twojadomena.pl;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self'" always;
}Jak sprawdzić nagłówki bezpieczeństwa?
- Wirtualna Tarcza - automatyczna ocena wszystkich nagłówków z oceną A-F i konkretnymi instrukcjami naprawy
- Mozilla Observatory (observatory.mozilla.org) - szczegółowy scoring z uzasadnieniem każdego punktu
- SecurityHeaders.com - szybkie sprawdzenie bez rejestracji
- curl -I https://twojadomena.pl - ręczne sprawdzenie w terminalu
- Chrome DevTools → Network → Response Headers - podgląd nagłówków dla konkretnego żądania