Secure Cookie Configuration with AI Prompts

TL;DR

Cookie security depends on proper attributes: HttpOnly prevents XSS access, Secure ensures HTTPS-only, SameSite prevents CSRF. Most session cookies should have all three. These prompts help you audit your cookies and set them up correctly.

Use this prompt to find every cookie your application sets and check its security attributes. Your AI will flag auth cookies missing HttpOnly, production cookies without Secure, and overly broad Domain scoping.

AI Prompt

Audit Cookie Configuration

Audit all cookies my application sets for security issues.

For each cookie, check:

  1. HttpOnly: Is it set? (Required for auth cookies)
  2. Secure: Is it set? (Required for production)
  3. SameSite: What value? (Lax minimum for auth)
  4. Domain: Is it properly scoped?
  5. Path: Is it properly scoped?
  6. Max-Age/Expires: Appropriate lifetime?

Find all places cookies are set:

  • res.cookie() calls
  • Set-Cookie headers
  • document.cookie assignments
  • Framework session configuration

Flag issues:

  • Session/auth cookies without HttpOnly
  • Any cookie without Secure in production
  • SameSite=None without Secure
  • Overly broad Domain scope
  • Very long expiration for session cookies

Copy this prompt to configure your session cookie with HttpOnly, Secure, and SameSite attributes. Your AI will generate framework-specific code with proper settings for both production HTTPS and local HTTP development.

AI Prompt

Configure Session Cookie

Configure my session cookie with proper security attributes.

Framework: [Next.js/Express/Django]

Recommended settings: Set-Cookie: session=value; HttpOnly; Secure; SameSite=Lax; Path=/

Express example: res.cookie('session', sessionId, { httpOnly: true, // Not accessible via JavaScript secure: true, // HTTPS only sameSite: 'lax', // CSRF protection path: '/', // Available site-wide maxAge: 24 * 60 * 60 * 1000, // 24 hours // domain: omit unless needed for subdomains });

For development (HTTP localhost): secure: process.env.NODE_ENV === 'production'

Note: SameSite=Strict breaks OAuth flows SameSite=Lax is usually the right choice

HttpOnly is essential for auth cookies: Without it, any XSS on your site can steal session cookies. It's the difference between XSS being annoying and XSS being a full account takeover.

SameSite Attribute Guide

This prompt asks your AI to help you choose the right SameSite value for each of your cookies. You'll get a clear explanation of Strict, Lax, and None with concrete examples showing when each is appropriate.

AI Prompt

SameSite Configuration

Choose the right SameSite value for my cookies.

SameSite options:

Strict:

  • Cookie only sent for same-site requests
  • Most secure but can break legitimate flows
  • User clicking link from email won't be logged in
  • Use for: high-security banking, admin panels

Lax (Recommended default):

  • Sent for same-site + top-level navigation
  • Good balance of security and usability
  • User clicking link from email stays logged in
  • Use for: most session cookies

None:

  • Sent with all requests (cross-site too)
  • Must be used with Secure
  • Needed for: cross-site iframes, third-party contexts
  • Use sparingly and only when required

Examples: // Standard session sameSite: 'lax'

// Admin session (extra security) sameSite: 'strict'

// Third-party widget that needs auth sameSite: 'none', secure: true

Leaving SameSite unset is not the same as setting it

Chrome treats a cookie with no SameSite attribute as Lax. That sounds like you can skip the attribute and get the protection for free. You can't.

When Lax is applied as a default rather than written down, browsers use a looser version of it: the cookie is still sent on cross-site POST requests made within two minutes of being set. That two-minute window exists so old login flows did not break overnight when the default changed. It is a compatibility concession, and it is open on every cookie you forget to label.

Writing SameSite=Lax explicitly closes it. Same value, different behaviour, and the audit prompt above will not flag the gap unless you ask it to, because the cookie technically "is" Lax either way.

The default also varies by browser. Chromium applies Lax-by-default; not every engine does, and the two-minute POST carve-out is specific to the implicit case. A cookie that relies on the default is relying on each browser agreeing with Chrome. Set the attribute.

The audit prompt asks whether your cookie lifetimes are appropriate. Here is the number it should be measured against: 400 days.

Since Chrome 104 (August 2022), any Max-Age or Expires value further out than 400 days is clamped down to 400 days. The cookie is not rejected and no error is logged, so a "remember me for 5 years" cookie looks like it worked and quietly expires after thirteen months. Session cookies, the ones with no expiry set at all, are unaffected: they still clear when the browsing session ends.

If you need a longer-lived login, refresh the cookie on each visit by setting it again with the same name rather than asking for a date the browser will ignore.

Why 400 and not 365? Chrome picked slightly over thirteen months so that a site someone visits once a year, on roughly the same date, still recognises them on the next visit.

Use this prompt to add __Secure- and __Host- prefixes to your cookies for browser-enforced security. Your AI will show you how to implement the strictest __Host- prefix, which prevents subdomain cookie injection attacks.

AI Prompt

Use Cookie Prefixes

Use cookie prefixes for additional security enforcement.

Cookie prefixes tell browsers to require certain attributes:

__Secure- prefix:

  • Cookie must have Secure attribute
  • Must be set over HTTPS Set-Cookie: __Secure-session=value; Secure; ...

__Host- prefix (strictest):

  • Must have Secure attribute
  • Must NOT have Domain attribute
  • Path must be /
  • Prevents subdomain attacks Set-Cookie: __Host-session=value; Secure; Path=/

Using __Host- prefix: res.cookie('__Host-session', value, { httpOnly: true, secure: true, sameSite: 'lax', path: '/' // No domain attribute! });

Benefits:

  • Browser enforces security even if code has bugs
  • __Host- prevents subdomain cookie injection attacks
  • Defense in depth

Pro tip: Test your cookies at https://securityheaders.com or in browser DevTools (Application > Cookies). You can see all attributes and quickly spot missing security flags.

Do You Still Need SameSite=None?

Short answer: yes, and it is no longer a temporary measure.

Google spent five years saying it would phase third-party cookies out of Chrome. In April 2025 it stopped saying that. The Privacy Sandbox team confirmed Chrome will keep its existing third-party cookie choice and will not ship the standalone prompt that was supposed to replace it. So if your app embeds an authenticated widget or runs inside someone else's iframe, SameSite=None; Secure is the mechanism, and planning a migration off it is work you do not need to do.

The catch is that Chrome is not the whole web. Safari and Firefox block third-party cookies by default already, and no attribute you set changes that. SameSite=None means "send this cross-site if the browser allows it", not "make the browser allow it". If a cross-site feature has to work everywhere, it needs a design that survives the cookie being dropped.

SameSite=None without Secure is not a weaker cookie, it is a rejected one. Browsers refuse the whole Set-Cookie header. The usual symptom is a login that silently never persists, with nothing in the server logs, because the cookie was discarded on the client.

Why doesn't my cookie work in development?

Secure cookies only work over HTTPS. For localhost development, either use HTTPS (mkcert), or conditionally disable Secure in dev, but always enable it in production.

My OAuth login broke after adding SameSite. What do I do?

OAuth redirects are cross-site. Use SameSite=Lax (not Strict), which allows cookies on top-level navigations. If you authenticate inside an iframe, you need SameSite=None with Secure.

Is leaving SameSite unset the same as setting SameSite=Lax?

No. Chrome treats a cookie with no SameSite attribute as Lax, but it applies a more permissive version that still sends the cookie on POST requests made within two minutes of the cookie being set. Setting SameSite=Lax explicitly closes that window.

What is the longest a cookie can live?

400 days. Since Chrome 104 (August 2022), any Max-Age or Expires value beyond 400 days is silently clamped to 400 days rather than rejected. Session cookies with no expiry set are unaffected. For a longer-lived login, re-set the cookie on each visit.

Further Reading

Want to understand the vulnerability before fixing it? These guides explain what's happening and why.

Scan your application for insecure cookie configuration.

AI Fix Prompts

Secure Cookie Configuration with AI Prompts