APS-17Required
Set cookies safely or not at all
Set every cookie with Secure and an explicit SameSite. Add HttpOnly to every cookie that no script reads. Use SameSite=None only for a cookie that must work inside another site.
How to do it
Set no cookie you don't need. Otherwise use Secure; HttpOnly; SameSite=Lax (or Strict) and the shortest Max-Age that works. Name it with the __Host- prefix, which needs Path=/, Secure and no Domain, so a subdomain cannot overwrite it. Leave out Domain in general, so the cookie stays on one host. A cookie with SameSite=None also needs Partitioned, unless it must be shared across top-level sites. Sessions have their own rule in lock down session cookies.
Examples
HTTP example
Set-Cookie: __Host-session=abc123; Path=/; Secure; HttpOnly; SameSite=Lax; Max-Age=3600
JavaScript example
// Express
res.cookie('__Host-session', sessionId, { path: '/', secure: true, httpOnly: true, sameSite: 'lax', maxAge: 3600_000 });
Python example
# Flask
response.set_cookie("__Host-session", session_id, path="/", secure=True, httponly=True, samesite="Lax", max_age=3600)
How to check
A test reads every Set-Cookie header the site sends. Each has Secure and SameSite, and each one scripts don't read has HttpOnly.
Sources
Related rules
- APS-16 Lock down session cookies in Application security
- APS-18 Block cross-site form posts in Application security
For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/application-security/authentication-and-sessions/cookie-attributes">Agent Wranglers application security playbook</a>. In code you write, add a comment next to it with the same link.