# Session cookies have Secure and HttpOnly flags

- **Pattern:** `ab-000003` (`security-headers.transport.secure-cookies`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-04-17
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000003
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000003)

## Why it matters

Session cookies without `Secure` can be transmitted over plain HTTP if a downgrade or redirect is ever triggered, handing an attacker the session token in cleartext. Cookies without `HttpOnly` are readable by any JavaScript on the page — a single XSS payload is enough to exfiltrate the token to an attacker-controlled server. Together, these two flags prevent the most common session-theft vectors. OWASP A05 (Security Misconfiguration) and A07 (Identification and Authentication Failures) both flag missing cookie security attributes as prerequisites for session hijacking. CWE-614 and CWE-1004 explicitly name the absence of `Secure` and `HttpOnly` as exploitable defects.

## Severity rationale

High because missing Secure or HttpOnly flags on session cookies are direct prerequisites for session hijacking via network interception or XSS.

## Remediation

Verify your auth library's cookie configuration explicitly sets both flags. Most libraries set them by default in production, but explicit config overrides defaults and survives library upgrades without silent regression.

```ts
// NextAuth.js — src/app/api/auth/[...nextauth]/route.ts or auth.ts
export const authOptions = {
  cookies: {
    sessionToken: {
      options: { httpOnly: true, secure: true, sameSite: 'lax' }
    }
  }
}
```

For manual `Set-Cookie` headers in API routes, append `; HttpOnly; Secure; SameSite=Lax` to every cookie value. Search all API routes for `Set-Cookie` and `document.cookie` to find uncovered locations.

## Detection

- **ID:** `secure-cookies`
- **Severity:** `high`
- **What to look for:** Count all cookie-setting locations in the codebase: auth library config (next-auth options, Supabase cookie config, clerk config), middleware that sets cookies, manual `Set-Cookie` headers in API routes, and any `document.cookie` assignments. For each cookie-setting location, check for `secure: true` and `httpOnly: true` flags.
- **Pass criteria:** 100% of cookies set by the application are configured with both `Secure` and `HttpOnly` flags. Auth libraries that set these by default in production count as passing (e.g., NextAuth.js sets these by default). Report: "X cookie-setting locations found, all Y cookies configured with Secure and HttpOnly."
- **Fail criteria:** Any cookies are set without `Secure` or without `HttpOnly`, or cookie configuration explicitly disables these flags.
- **Do NOT pass when:** Secure flags are set in code but overridden by framework defaults, middleware, or a wrapper function that strips cookie options.
- **Skip (N/A) when:** No cookies of any kind are set by the application — no Set-Cookie headers, no document.cookie assignments, no cookie library usage.
- **Cross-reference:** For authentication flow security beyond cookie flags, the Auth & Session Security audit covers session management, token rotation, and session fixation in depth.
- **Detail on fail:** `"NextAuth session cookie configured without httpOnly flag in auth options"` or `"Manual Set-Cookie in API route /api/session does not include Secure flag"`
- **Remediation:** The `Secure` flag ensures cookies are only sent over HTTPS. The `HttpOnly` flag prevents JavaScript from reading the cookie, mitigating XSS-based session theft. Most auth libraries set these by default, but verify your configuration:

  ```ts
  // NextAuth example
  export const authOptions = {
    cookies: {
      sessionToken: {
        options: { httpOnly: true, secure: true, sameSite: 'lax' }
      }
    }
  }
  ```

## External references

- cwe CWE-614
- cwe CWE-1004
- owasp A05
- owasp A07

Taxons: access-control, cryptography-and-secrets

HTML version: https://auditbuffet.com/patterns/ab-000003
