Rules Hub
Code Ruleset
Rule priority, scope & exceptions
Use this to align rules with the senior-level structure (P0/P1/P2, scope, exceptions/tradeoffs).
Don't store auth tokens in localStorage/sessionStorage; use HttpOnly cookies
Browser-accessible storage (localStorage/sessionStorage/JS memory) for session or refresh tokens is XSS-exfiltratable; keep them in HttpOnly cookies.
Bad example
| 1 | // React login handler |
| 2 | const { token } = await api.login(email, password); |
| 3 | localStorage.setItem('accessToken', token); // readable by any script on the page |
| 4 |
|
| 5 | // later, on every request |
| 6 | fetch('/api/me', { |
| 7 | headers: { Authorization: `Bearer ${localStorage.getItem('accessToken')}` }, |
| 8 | }); |
Explanation (EN)
Persistent script-readable token storage increases credential exfiltration exposure.
Objašnjenje (HR)
Trajna pohrana tokena dostupna skriptama povećava izloženost krađi vjerodajnice.
Good example
| 1 | // Server sets the session in an HttpOnly cookie (Next.js Route Handler) |
| 2 | import { cookies } from 'next/headers'; |
| 3 |
|
| 4 | export async function POST(req: Request) { |
| 5 | const { email, password } = await req.json(); |
| 6 | const session = await login(email, password); |
| 7 | (await cookies()).set('session', session.id, { |
| 8 | httpOnly: true, secure: true, sameSite: 'lax', path: '/', |
| 9 | }); |
| 10 | return Response.json({ ok: true }); |
| 11 | } |
| 12 |
|
| 13 | // Client just relies on the cookie being sent automatically |
| 14 | await fetch('/api/me', { credentials: 'same-origin' }); // no token in JS at all |
Explanation (EN)
The route sets a secure HttpOnly session cookie through the asynchronous cookies API; client scripts do not receive the session ID, while CSRF and XSS defenses remain necessary.
Objašnjenje (HR)
Ruta postavlja sigurni HttpOnly sesijski cookie asinkronim cookies API-jem. Klijentske skripte ne dobivaju ID sesije, ali CSRF i XSS zaštita i dalje su potrebne.
Notes (EN)
For a browser session architecture under your control, prefer an HttpOnly secure cookie so application scripts do not need access to the session credential.
Bilješke (HR)
Za arhitekturu browser sesije koju kontroliraš prednost daj sigurnom HttpOnly cookieju kako aplikacijske skripte ne bi morale čitati sesijsku vjerodajnicu.
Exceptions / Tradeoffs (EN)
If your architecture genuinely requires bearer tokens in JS (e.g. a cross-origin API you don't control), keep the access token short-lived and in memory only (not localStorage), keep the refresh token in an HttpOnly cookie, and rely on a strict CSP to reduce XSS reach. Cookie-based sessions still require CSRF protection (SameSite + token). HttpOnly prevents direct script reads but does not stop XSS from issuing authenticated requests. Preserve CSRF defenses, origin policy and any necessary short-lived in-memory bearer-token flow.
Iznimke / Tradeoffi (HR)
Ako arhitektura zahtijeva bearer token dostupan JavaScriptu, drži ga kratkotrajno u memoriji, bez localStoragea; refresh token zaštiti HttpOnly cookiejem kada arhitektura to omogućuje. CSP smanjuje dio XSS rizika. Cookie sesije i dalje trebaju CSRF i origin zaštitu. HttpOnly sprječava čitanje cookieja, ali ne sprječava XSS u slanju autoriziranih zahtjeva.