Rules Hub
Code Ruleset
Rule priority, scope & exceptions
Use this to align rules with the senior-level structure (P0/P1/P2, scope, exceptions/tradeoffs).
Set HttpOnly, Secure, and SameSite on every session/auth cookie
Cookies that carry a session ID or auth token must be HttpOnly + Secure + SameSite with a constrained scope, not framework defaults.
Bad example
| 1 | // Express: session cookie with no security attributes |
| 2 | res.cookie('sid', sessionId); |
| 3 |
|
| 4 | // or express-session left on defaults |
| 5 | app.use( |
| 6 | session({ |
| 7 | secret: process.env.SESSION_SECRET!, |
| 8 | resave: false, |
| 9 | saveUninitialized: false, |
| 10 | // cookie: {} -> HttpOnly true by default, but Secure/SameSite NOT enforced |
| 11 | }), |
| 12 | ); |
Explanation (EN)
Relying on implicit defaults can expose a session to insecure transport or unintended cross-site requests.
Objašnjenje (HR)
Oslanjanje na neizričite zadane vrijednosti može izložiti sesiju nesigurnom prijenosu ili nenamjernim cross-site zahtjevima.
Good example
| 1 | res.cookie('sid', sessionId, { |
| 2 | httpOnly: true, // not readable from JS -> XSS can't exfiltrate it |
| 3 | secure: true, // HTTPS only |
| 4 | sameSite: 'lax', // 'strict' for pure first-party; 'none' (with secure) only for cross-site |
| 5 | path: '/', |
| 6 | maxAge: 1000 * 60 * 60 * 8, // bounded lifetime; prefer rolling expiry |
| 7 | }); |
| 8 |
|
| 9 | // express-session |
| 10 | app.use( |
| 11 | session({ |
| 12 | secret: process.env.SESSION_SECRET!, |
| 13 | resave: false, |
| 14 | saveUninitialized: false, |
| 15 | cookie: { httpOnly: true, secure: true, sameSite: 'lax', maxAge: 28800000 }, |
| 16 | }), |
| 17 | ); |
Explanation (EN)
Explicit HttpOnly + Secure + SameSite + bounded Max-Age make the cookie unreadable from JS, transport-encrypted, and resistant to CSRF, with a lifetime that limits replay. Stating the flags at the call site means the security posture does not depend on framework defaults.
Objašnjenje (HR)
Eksplicitni HttpOnly + Secure + SameSite + ograniceni Max-Age cine kolacic necitljivim iz JS-a, sifriranim u prijenosu i otpornim na CSRF, uz vijek trajanja koji ogranicava ponovnu uporabu. Navodenjem zastavica na mjestu poziva sigurnosno ponasanje ne ovisi o zadanim vrijednostima frameworka.
Notes (EN)
For session cookies, explicitly choose HttpOnly, Secure, SameSite, host/path scope and lifetime for the deployed origin and authentication flow.
Bilješke (HR)
Za sesijske cookieje izričito odredi HttpOnly, Secure, SameSite, host, putanju i rok prema produkcijskom originu i autentifikacijskom toku.
Exceptions / Tradeoffs (EN)
Use sameSite:'none' (always with secure:true) only when the cookie genuinely must travel cross-site (e.g. embedded SSO). In local development over http you may relax secure behind an env check, but never ship secure:false. Non-auth, deliberately client-readable cookies (e.g. a theme preference) are out of scope. These attributes do not replace CSRF/origin checks, server-side expiry or XSS prevention. Cookie paths are routing scope, not a security boundary; omit Domain when a host-only cookie is intended.
Iznimke / Tradeoffi (HR)
SameSite=None uz Secure=True koristi samo za potreban cross-site tok. Lokalni HTTP razvoj može imati posebno ograničenu iznimku za Secure. Namjerno klijentski čitljivi cookieji bez autentifikacijskih podataka nisu obuhvaćeni. Ovi atributi ne zamjenjuju CSRF/origin provjere, serverski istek ni XSS zaštitu. Putanja cookieja nije sigurnosna granica; za host-only cookie izostavi Domain.