# Session fixation protection is in place

- **Pattern:** `ab-002207` (`saas-authentication.session-management.session-fixation`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-002207
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-002207)

## Why it matters

Session fixation (CWE-384, CAPEC-61) lets an attacker plant a known session token in a victim's browser before login, then use that same token after the victim authenticates. The attacker never needs to steal anything — they supplied the token themselves. This attack predates modern auth libraries and is largely invisible in code review because the vulnerability is an absence: the session is never regenerated after login. OWASP A07 (Identification and Authentication Failures) lists session fixation as a named failure mode, and the OWASP ASVS Session Management chapter requires that session identifiers be regenerated on authentication.

## Severity rationale

High because a successful session fixation attack gives the attacker an authenticated session for any user they can trick into logging in, with no stolen credentials required.

## Remediation

After successful credential verification, always replace the pre-login session with a freshly generated one before setting any user data on it:

```ts
// Express/Fastify — regenerate before setting user data
app.post('/login', async (req, res) => {
  const user = await verifyCredentials(req.body)
  if (!user) return res.status(401).json({ error: 'Invalid credentials' })
  req.session.regenerate((err) => {
    if (err) return res.status(500).json({ error: 'Session error' })
    req.session.userId = user.id
    req.session.save(() => res.json({ ok: true }))
  })
})
```

Managed libraries (NextAuth, Clerk, Supabase Auth) regenerate sessions after login by design. If you have overridden the session token generation logic in any of these libraries, revert to the default.

## Detection

- **ID:** `session-fixation`
- **Severity:** `high`
- **What to look for:** Examine the login flow. After successful authentication, a new session token should be generated — never reusing the pre-login session ID. Look for session regeneration calls after login (e.g., `req.session.regenerate()` in Express/Fastify). For cookie-based auth: check that the session cookie set after login is freshly generated, not derived from any pre-auth value. Managed auth providers (NextAuth, Clerk, Supabase Auth) handle this correctly by design. Count all instances found and enumerate each.
- **Pass criteria:** A fresh, cryptographically random session token is generated upon successful login. The pre-login session (if any) is discarded and a new one is issued. Libraries that implement this by default count as passing. At least 1 implementation must be confirmed.
- **Fail criteria:** Custom session implementation reuses a session ID that existed before login, or the session token is derived from a value the attacker could predict or set.
- **Skip (N/A) when:** Fully managed auth provider is used with default configuration (NextAuth, Clerk, Supabase Auth, Auth0, Firebase Auth) — session fixation is handled by the library. Signal: auth library in `package.json` with no custom session token generation code.
- **Detail on fail:** `"Custom session middleware at src/lib/session.ts reuses the existing session ID after login rather than regenerating it"` or `"Login handler at /api/auth/login updates session data but calls req.session.save() without req.session.regenerate()"`.
- **Remediation:** Session fixation attacks work by planting a known session ID before login and then using it to access the authenticated session. Fix it by regenerating the session after authentication:

  ```ts
  // Express/Fastify session example
  app.post('/login', async (req, res) => {
    const user = await verifyCredentials(req.body)
    if (!user) return res.status(401).json({ error: 'Invalid credentials' })

    // Regenerate session to prevent fixation
    req.session.regenerate((err) => {
      if (err) return res.status(500).json({ error: 'Session error' })
      req.session.userId = user.id
      req.session.save(() => res.json({ ok: true }))
    })
  })
  ```

  If using a managed auth library, verify you're using the default session handling and have not overridden the session token generation logic.

## External references

- cwe CWE-384
- owasp A07
- capec CAPEC-61

Taxons: access-control

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