# Session tokens in secure HTTP-only cookies, SameSite=Strict

- **Pattern:** `ab-001473` (`finserv-session-security.session-integrity.token-security-httponly`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001473
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001473)

## Why it matters

Session tokens stored in localStorage or accessible JavaScript variables are exfiltrable by any XSS payload on any page of the application. A single reflected or stored XSS vulnerability anywhere on the domain becomes a full session hijack with no additional effort. CWE-614 (Sensitive Cookie Without 'Secure' Attribute) and CWE-1004 (Sensitive Cookie Without 'HttpOnly' Flag) define these as distinct failures. OWASP A07 and PCI-DSS Req 6.4.1 mandate that session tokens be inaccessible to client-side scripts. In a financial application, exfiltrating a session token from localStorage via `document.cookie` or XSS requires zero CSRF bypass — the token is already JavaScript-readable and portable.

## Severity rationale

High because a session token in localStorage or a cookie missing HttpOnly is a single XSS vulnerability away from full account compromise — the attacker does not need to break HTTPS or defeat SameSite protections to extract and replay it.

## Remediation

Configure session cookies with all three required attributes in `src/lib/session.ts` or the session middleware initialization:

```js
session({
  cookie: {
    httpOnly: true,     // inaccessible to document.cookie and XSS
    secure: true,       // HTTPS transport only
    sameSite: 'Strict', // no cross-origin send (CSRF protection)
    maxAge: 15 * 60 * 1000
  }
})
```

Audit all calls to `localStorage.setItem` and `sessionStorage.setItem` in the codebase — no session token, auth token, or user identity value should appear as a storage key. Tokens are set exclusively by the server via `Set-Cookie` response headers; the client-side JavaScript never handles them.

## Detection

- **ID:** `token-security-httponly`
- **Severity:** `high`
- **What to look for:** Count all cookie configuration settings and enumerate the security attributes: httpOnly, secure, sameSite. Quote the actual values found. Count all localStorage/sessionStorage token stores. Verify at least 3 cookie security attributes are set: httpOnly=true, secure=true, sameSite=Strict. A token stored in localStorage must not pass — do not pass if any session token is JavaScript-accessible.
- **Pass criteria:** Session tokens stored in cookies with at least 3 security attributes: httpOnly=true, secure=true, sameSite=Strict. Count all token storage locations — 0 must use localStorage/sessionStorage. Report the count even on pass (e.g., "Cookie config: httpOnly=true, secure=true, sameSite=Strict — 3 of 3 attributes set, 0 localStorage stores").
- **Fail criteria:** Session tokens in localStorage/sessionStorage (even 1 instance), or cookies lack any of: httpOnly, secure, or sameSite=Strict.
- **Skip (N/A) when:** The application uses stateless JWT with no cookies — cite the actual auth mechanism found.
- **Detail on fail:** `"Session token in localStorage — JavaScript-accessible. 0 of 3 required cookie attributes (httpOnly, secure, sameSite) applicable"` or `"Cookie has httpOnly=true but secure=false — 2 of 3 required attributes set"`
- **Remediation:** Use secure HTTP-only cookies (in `src/lib/session.ts` or session middleware config):
  ```js
  // session middleware configuration
  session({
    cookie: {
      httpOnly: true,   // Prevent JavaScript access
      secure: true,     // HTTPS only
      sameSite: 'Strict', // Prevent CSRF
      maxAge: 15 * 60 * 1000, // 15 minutes
      domain: 'yourdomain.com'
    }
  })

  // Never store tokens in localStorage
  // localStorage.setItem('token', sessionToken); // DON'T DO THIS
  // Cookies are set automatically by the server
  ```

## External references

- cwe CWE-614
- cwe CWE-1004
- owasp A07
- pci-dss Req 6.4.1

Taxons: cryptography-and-secrets, access-control

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