Niemal każda dziura w aplikacji Next.js tworzonej przez AI bierze się z jednego nieporozumienia: niewiedzy, która część kodu działa na serwerze, a która trafia do przeglądarki. Next.js miesza obie w tym samym projekcie, a Cursor, v0 czy Bolt przekraczają tę granicę bez ostrzeżenia. Ten przewodnik wyjaśnia ten model myślowy w pięć minut, omawia, co narzędzia AI robią źle w Next.js, zostawia Ci blok reguł do wklejenia w projekt, prompt do przeglądu i cztery kontrole z zewnątrz. Lista punkt po punkcie, co naprawić, jest w checkliście Next.js przed startem; tutaj jest dlaczego.
Część 1: gdzie działa każda rzecz
Pięć miejsc, dwa światy
W App Routerze Twój kod może żyć w pięciu miejscach: Server Components (tylko serwer, nigdy nie trafiają do przeglądarki), Client Components (oznaczone "use client", wysyłane do przeglądarki w całości), Route Handlers (app/api/.../route.ts, publiczne URL-e), Server Actions (funkcje z "use server", które klient wywołuje przez POST) i middleware (w najnowszych wersjach nazywany proxy), który działa przed każdym żądaniem. Trzy ostatnie plus Server Components to świat serwera; Client Components to świat przeglądarki. Wszystko, co importujesz w Client Component, łącznie ze stałymi i funkcjami pomocniczymi, wędruje do bundle'a.
Co trafia do przeglądarki
- Zmienne środowiskowe z prefiksem
NEXT_PUBLIC_, wbudowane w czasie builda. Pozostałe istnieją tylko na serwerze. - Każde dane, które Server Component przekazuje jako prop do Client Component. Jeśli przekazujesz cały obiekt
user, podróżuje on z hashem hasła i e-mailem. - Pliki z katalogu
public/, bez zmian. - Source mapy, jeśli włączysz je przez
productionBrowserSourceMaps.
Trzy mechanizmy, które zapobiegają przekraczaniu granicy
Pakiet server-only: import 'server-only' na początku pliku sprawia, że build pada, jeśli ktoś zaimportuje go z Client Component. Używaj go we wszystkim, co dotyka bazy danych lub czyta sekrety. Warstwa dostępu do danych: jeden moduł, który centralizuje sprawdzanie sesji i zwraca tylko potrzebne pola (DTO), zamiast odpytywać bazę z każdej strony. I zasada, że każdy punkt wejścia sprawdza sesję: Route Handlers, Server Actions i Server Components czytające prywatne dane, każdy z osobna. Middleware nie zastępuje tej kontroli, co pokazała CVE-2025-29927.
Czego Next.js za Ciebie nie robi
Nie dodaje nagłówków bezpieczeństwa, nie limituje żądań, nie waliduje danych wejściowych Server Actions i nie chroni ścieżek tylko dlatego, że leżą w katalogu o nazwie (admin). To wszystko jest Twoim kodem albo konfiguracją w next.config.
Część 2: co AI robi źle w Next.js
- Wszystko z "use client". Gdy komponent potrzebuje stanu, AI oznacza go jako kliencki i ciągnie za nim zapytanie do bazy albo klucz API. Rozdziel: komponent serwerowy pobiera dane, kliencki tylko rysuje.
- Ochrona tylko w middleware. Middleware przekierowuje, gdy nie ma ciasteczka, a handler mu ufa. Sprawdzaj sesję także w handlerze; tego nauczyła CVE middleware'u, a wersje starsze niż 15.2.3 lub 14.2.25 pozostają podatne.
- Route Handlers i Server Actions bez uwierzytelnienia i walidacji. Server Action to publiczny endpoint, nawet bez widocznego URL-a. Sprawdź, kto wywołuje, i zwaliduj body schematem (zod lub podobnym), zanim cokolwiek zrobisz.
- Sekrety z publicznym prefiksem.
NEXT_PUBLIC_OPENAI_KEY, bo komponent kliencki „go potrzebował". Klucz idzie do Route Handlera, a klient wywołuje handler. - remotePatterns z wildcardem.
hostname: '**'w konfiguracji obrazów zamienia Twój optymalizator obrazów w otwarte proxy dla dowolnego URL-a. - Przekierowania z parametrem.
redirect(searchParams.next)bez sprawdzenia, czy cel jest wewnętrzną ścieżką: phishing na Twojej domenie. - fetch do URL-i użytkownika. Handler, który pobiera, co mu podadzą, może dotrzeć do wewnętrznych usług Twojej sieci lub dostawcy.
- dangerouslySetInnerHTML z treścią użytkownika. Klasyczny XSS; jeśli potrzebujesz HTML-a, oczyść go na serwerze.
- Bez nagłówków i limitów. Ani CSP, ani HSTS, ani X-Frame-Options, i endpoint wywołujący płatny model bez limitu na użytkownika.
Blok reguł dla Twojego projektu
Wklej go do pliku reguł, który czyta Twoje narzędzie (.cursor/rules, AGENTS.md lub odpowiednik), żeby obowiązywał przy każdym generowaniu:
Reguły bezpieczeństwa dla tego projektu Next.js:
- Komponenty są Server Components, chyba że potrzebują stanu lub zdarzeń przeglądarki. Client Component nigdy nie importuje modułów, które sięgają do bazy danych lub czytają process.env bez prefiksu.
- Każdy moduł dotykający bazy danych lub sekretów zaczyna się od import 'server-only'.
- Nigdy nie używaj NEXT_PUBLIC_ dla sekretnego klucza. Wywołania usług z kluczem idą do Route Handlera lub Server Action.
- Każdy Route Handler i każda Server Action sprawdza sesję i waliduje dane wejściowe schematem, zanim cokolwiek zrobi. Middleware nie liczy się jako uwierzytelnienie.
- Przekazuj Client Components tylko potrzebne pola, nigdy cały obiekt użytkownika ani wiersza.
- Przekierowania akceptują tylko wewnętrzne ścieżki zaczynające się od pojedynczego ukośnika.
- images.remotePatterns wymienia konkretne domeny, nigdy wildcard hosta.
- Nie używaj dangerouslySetInnerHTML z treścią użytkownika.
- next.config definiuje nagłówki bezpieczeństwa i nie włącza productionBrowserSourceMaps.
Prompt do przeglądu przed wdrożeniem
Przejrzyj bezpieczeństwo tej aplikacji Next.js i na razie niczego nie zmieniaj. Odpowiedz listą:
1. Client Components, które importują moduły bazy danych, czytają sekrety lub otrzymują jako props obiekty z wrażliwymi polami.
2. Route Handlers i Server Actions bez sprawdzania sesji lub bez walidacji danych wejściowych.
3. Ścieżki, których jedyną ochroną jest middleware.
4. Zmienne NEXT_PUBLIC_ zawierające sekretne klucze.
5. Przekierowania przyjmujące cel od użytkownika, fetch do URL-i użytkownika i użycia dangerouslySetInnerHTML.
6. remotePatterns z wildcardem, włączone productionBrowserSourceMaps i brak nagłówków bezpieczeństwa w next.config.
7. Wersja Next.js i czy jest starsza niż 15.2.3 lub 14.2.25.
Dla każdego punktu zaproponuj dokładną zmianę i poczekaj na moje potwierdzenie.
Sprawdź wynik z zewnątrz
Cztery polecenia na Twoją domenę. Nagłówki i wersja middleware'u:
curl -sI https://twojadomena.com | grep -iE "strict-transport|content-security|x-frame|x-content-type"
curl -s -o /dev/null -w "%{http_code}\n" -H "x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware" https://twojadomena.com/dashboard
Jeśli drugie zwraca 200 na ścieżce, która powinna przekierować do logowania, Twoja wersja jest podatna na CVE middleware'u: zaktualizuj dziś. Potem source mapy i ścieżki API, które zdradza bundle:
curl -s https://twojadomena.com | grep -oE '/_next/static/chunks/[^"]+\.js' | head -3
curl -s https://twojadomena.com/_next/static/chunks/main-app-XXXX.js | grep -oE '"/api/[^"]+"' | sort -u
Odpytaj każdą ścieżkę API bez sesji: prawidłowa odpowiedź to 401 lub 403. Scanaris wykonuje te kontrole i około czterdziestu innych w 30 sekund: wykrywa, że aplikacja to Next.js i jaka wersja, testuje nagłówek CVE, szuka sekretów w chunkach, sprawdza, czy source mapy są opublikowane, weryfikuje nagłówki, CSP, ciasteczka, CORS i wystawione pliki, a dla każdego błędu daje fix prompt do wklejenia w Cursorze lub v0. Jeśli wdrażasz na Vercelu, przewodnik po Vercelu obejmuje publiczne podglądy i zmienne środowiskowe.
Często zadawane pytania
Czy Server Actions są domyślnie bezpieczne?
Trudniej je odkryć niż Route Handler, ale są równie publiczne: każdy z identyfikatorem akcji może ją wywołać. Traktuj je jak endpoint: sesja i walidacja wewnątrz funkcji.
Czy middleware wystarczy, żeby chronić panel?
Nie. Przydaje się do szybkiego przekierowania, ale prawdziwa kontrola należy do każdej strony, handlera i akcji. CVE-2025-29927 pozwalała ominąć middleware jednym nagłówkiem; nawet na załatanej wersji zasada pozostaje ta sama.
Czy mogę dalej używać Pages Routera?
Tak, i model jest ten sam: getServerSideProps i pages/api to serwer, reszta to klient. Zwracaj z getServerSideProps tylko to, czego strona potrzebuje, bo wszystko, co zwrócisz, jest serializowane do HTML-a.