Kiedy wypuszczasz aplikację zrobioną w Cursorze, Lovable czy v0, serwer odpowiada na każde żądanie serią nagłówków HTTP: niewidocznych instrukcji, których przeglądarka słucha, zanim cokolwiek narysuje. Garść z nich decyduje o sporej części bezpieczeństwa Twojej strony, a prawie żaden szablon nie ma ich włączonych. Ten poradnik wyjaśnia, co robi każdy z nich, jaką wartość ustawić, jakie błędy psują rzeczy i jak je skonfigurować na Vercelu, w Next.js, Nuxt, Netlify, Cloudflare lub nginx.
Czym jest nagłówek i jak zobaczyć swoje
Nagłówek to linia tekstu towarzysząca odpowiedzi, w formie Nazwa: wartość. Przeglądarka ją czyta i zmienia zachowanie: ładuje skrypt albo nie, wymusza HTTPS, pozwala umieścić Twoją stronę w iframe albo nie. Zobaczysz je w narzędziach deweloperskich (F12, zakładka Network, kliknięcie głównego dokumentu, sekcja Response Headers) albo z terminala:
curl -I https://twojadomena.pl
Jeśli na tej liście nie ma tych poniżej, nie są skonfigurowane. Nie ma wartości domyślnych, które Cię uratują.
Siedem, które się liczą
Content-Security-Policy (CSP)
Królowa. Mówi przeglądarce, z jakich źródeł może ładować skrypty, style, obrazy, czcionki i połączenia. Jeśli atakującemu uda się wstrzyknąć <script> na Twoją stronę, dobra CSP nie pozwoli go wykonać. Uczciwy punkt wyjścia dla nowoczesnej aplikacji:
Content-Security-Policy: default-src 'self'; script-src 'self' https://js.stripe.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; connect-src 'self' https://*.supabase.co; frame-ancestors 'none'; base-uri 'self'; form-action 'self'
Typowy błąd to wstawienie 'unsafe-inline' do script-src, bo „inaczej nie działa": to wyrzuca główną ochronę do kosza. Nowoczesne frameworki rozwiązują skrypty inline przez nonce (losową wartość na żądanie) albo hashe. A bezpieczny sposób, żeby zacząć, to tryb raportowania: nagłówek Content-Security-Policy-Report-Only niczego nie blokuje, tylko mówi, co by zablokował. Zostaw go tak kilka dni, przejrzyj raporty i przełącz na prawdziwy nagłówek, gdy już niczego nie psuje.
Strict-Transport-Security (HSTS)
Zmusza przeglądarkę do używania HTTPS przez wskazany czas, nawet jeśli użytkownik wpisze http:// albo kliknie stary link. Zapobiega temu, by ktoś w tej samej sieci obniżył połączenie. Zwykła wartość:
Strict-Transport-Security: max-age=31536000; includeSubDomains
Włącz go dopiero, gdy cała Twoja domena i subdomeny chodzą po HTTPS: jeśli ustawisz go z subdomeną wciąż na HTTP, zablokujesz ją na rok w każdej przeglądarce, która ten nagłówek widziała. W razie wątpliwości zacznij od krótkiego max-age.
X-Frame-Options i frame-ancestors
Nie pozwalają załadować Twojej strony w <iframe> innej strony. Bez nich ktoś może osadzić Twoją aplikację w fałszywej witrynie i nakłonić użytkowników do klikania tam, gdzie nie powinni: to clickjacking. X-Frame-Options: DENY lub SAMEORIGIN załatwia to w starych przeglądarkach; nowoczesna forma to dyrektywa frame-ancestors w CSP. Ustaw obie.
X-Content-Type-Options
Jedna wartość: nosniff. Nie pozwala przeglądarce zgadywać typu pliku i wykonywać jako skrypt czegoś, co serwowałeś jako tekst albo obraz. To jedna linia; nie ma wymówki, żeby jej brakowało.
Referrer-Policy
Kontroluje, ile informacji z adresu źródłowego wysyła się przy przejściu na inną stronę albo ładowaniu zewnętrznego zasobu. Bez kontroli możesz wyciekać prywatne ścieżki albo tokeny podróżujące w URL-u. strict-origin-when-cross-origin to rozsądny kompromis: Twoja domena tak, pełna ścieżka nie.
Permissions-Policy
Deklaruje, z jakich możliwości przeglądarki może korzystać Twoja strona i jej iframe'y: kamera, mikrofon, geolokalizacja, płatności. Jeśli ich nie używasz, wyłącz je; wtedy wstrzyknięty skrypt ani iframe firmy trzeciej też nie będą mogły. Na przykład: camera=(), microphone=(), geolocation=().
Cross-Origin-Opener-Policy
Mniej znany: izoluje Twoje okno od tych, które je otworzyły lub które otworzyłeś przez window.open, co odcina całą rodzinę ataków między kartami. same-origin to zwykła wartość, chyba że polegasz na wyskakujących oknach firm trzecich (niektóre logowania OAuth), wtedy lepsze jest same-origin-allow-popups.
Które warto usunąć
X-Powered-By i nagłówek Server z wersją ogłaszają Twój dokładny stack każdemu, kto szuka znanych luk. W Next.js usuwa się go przez poweredByHeader: false; w Expressie przez app.disable('x-powered-by'). A X-XSS-Protection jest przestarzały: nowoczesne przeglądarki go ignorują, a w starych sam powodował błędy. Nie ustawiaj go albo ustaw na 0.
Jak je ustawić w zależności od hostingu
Vercel, dla dowolnego frameworka, w vercel.json:
{
"headers": [
{
"source": "/(.*)",
"headers": [
{ "key": "Strict-Transport-Security", "value": "max-age=31536000; includeSubDomains" },
{ "key": "X-Frame-Options", "value": "SAMEORIGIN" },
{ "key": "X-Content-Type-Options", "value": "nosniff" },
{ "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" },
{ "key": "Permissions-Policy", "value": "camera=(), microphone=(), geolocation=()" }
]
}
]
}
Next.js: funkcja headers() w next.config.js, z tą samą listą; CSP z nonce generuje się w middleware. Nuxt: routeRules w nuxt.config.ts z obiektem headers, albo plugin serwerowy, jeśli potrzebujesz nonce. Netlify: plik _headers w publikowanym folderze:
/*
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Cloudflare: reguły transformacji nagłówków odpowiedzi w panelu, bez dotykania kodu. nginx na VPS-ie:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
CSP celowo zostawiam poza tymi blokami: to jedyny nagłówek zależny od tego, jakich skryptów i usług używa Twoja aplikacja, i warto go budować w trybie raportowania, zanim się go utrwali.
Błędy, które psują rzeczy
- HSTS zanim wszystko jest na HTTPS. Odcina każdego, kto ma subdomenę na HTTP. Najpierw sprawdź, potem włącz.
- CSP bez nonce w Next.js lub Nuxt. Oba wstrzykują skrypty inline do hydratacji strony; bez nonce rygorystyczna CSP je blokuje i aplikacja zostaje biała. Użyj mechanizmu nonce frameworka.
- Nagłówki tylko na HTML-u. Route'y API i pliki statyczne też ich potrzebują, zwłaszcza
nosniff. Zastosuj regułę do/(.*). - Zduplikowane nagłówki. Jeśli CDN i aplikacja dodają ten sam, przeglądarka może zostać przy bardziej restrykcyjnym albo zignorować oba. Zdecyduj się na jedno miejsce.
- Zapomnienie o subdomenach (app., api., docs.): każda odpowiada własnymi nagłówkami.
Sprawdź je z zewnątrz
Te nagłówki to informacja publiczna: każdy może je odczytać, Ty też. Darmowe narzędzie do sprawdzania nagłówków w sekundy wypisze te, których brakuje i które są źle ustawione. A Scanaris robi pełną kontrolę tylko do odczytu, razem z około 45 innymi rzeczami, i do każdego brakującego nagłówka daje fix prompt gotowy do wklejenia w Twoje AI z dokładną linią dla Twojego hostingu. Niczego nie wykorzystuje ani nie dotyka Twojego serwera: czyta i mówi, co włączyć. Pełny kontekst znajdziesz w poradniku bezpieczeństwa aplikacji tworzonych przez AI i w checkliście startowej.
Najczęściej zadawane pytania
Czy nagłówki spowalniają stronę?
Nie. To kilkaset bajtów na odpowiedź, a przeglądarka przetwarza je w mikrosekundy. HSTS wręcz ją przyspiesza, bo oszczędza przekierowanie z HTTP na HTTPS przy kolejnych wizytach.
Co się stanie, jeśli nagłówek coś zepsuje na produkcji?
Usuń go albo poluzuj i wdróż ponownie: efekt jest natychmiastowy, z wyjątkiem HSTS, który przeglądarki pamiętają przez max-age. Dlatego CSP testuje się w trybie raportowania, a HSTS włącza na końcu.
Czy potrzebuję CSP, jeśli moja aplikacja jest mała?
Jeśli Twoja aplikacja ma formularz albo pokazuje treści użytkowników, tak: to obrona, która zamienia XSS w drobny incydent. Zacznij od pozostałych nagłówków, które są trywialne, a CSP dodaj w trybie raportowania, gdy będziesz mieć na nią jedno popołudnie.