No PII in browser storage (localStorage/sessionStorage); encrypted if needed
Why it matters
GDPR Art. 32 requires appropriate security measures for personal data, and storing PII in localStorage is a direct failure of that obligation: any JavaScript running on the page — including third-party analytics, ad scripts, or injected malicious code — can read localStorage in full. OWASP A02 (Cryptographic Failures) explicitly calls out sensitive data exposure via client-side storage as a top vulnerability. CWE-522 covers insufficiently protected credentials, which includes JWTs containing PII stored where XSS attacks can exfiltrate them. ISO-27001:2022 A.8.24 requires cryptographic protection of data at rest — but localStorage provides no encryption at all. If a user's email, name, or session token is in localStorage, a single XSS payload harvests it silently.
Severity rationale
Medium because exploitation requires a co-located XSS or malicious script, but that is a realistic threat given the volume of third-party analytics and tracking scripts most apps load.
Remediation
Move authentication tokens from localStorage to HttpOnly cookies set server-side. HttpOnly cookies are inaccessible to JavaScript by specification, eliminating the XSS exfiltration vector.
// app/api/auth/login/route.ts (Next.js)
import { cookies } from 'next/headers'
export async function POST(req: Request) {
const { email, password } = await req.json()
const token = await authenticateUser(email, password)
cookies().set('session', token, {
httpOnly: true, // inaccessible to JavaScript
secure: true, // HTTPS only
sameSite: 'lax', // CSRF protection
maxAge: 60 * 60 * 24 * 7,
path: '/',
})
return Response.json({ ok: true })
}
Audit all localStorage.setItem calls in the codebase. For each one, verify no PII (email, phone, full name, address) is stored. User preferences (theme, language) are safe to store in localStorage — contact information is not.
DetectionPro
The detection method for this pattern is part of AuditBuffet Pro.
The full method (what to look for, pass and fail conditions, and how results get reported) ships inside the Data Protection Audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
External references
- cwe · CWE-312 — Cleartext Storage of Sensitive Information
- cwe · CWE-522 — Insufficiently Protected Credentials
- owasp:2021 · A02 — Cryptographic Failures
- gdpr · Art. 32 — Security of processing
- iso-27001:2022 · A.8.24 — Use of cryptography
- soc2:2017 · C1.1 — Identification and protection of confidential information
Taxons
History
- 2026-04-18·v1.0.0·Initial import from data-protection·automated
- 2026-07-06·v1.0.1·Add SOC 2 TSC mapping (C1.1) from the verified compliance crosswalk register (docs/compliance/).·by soc2-mapping-enrichment-ship-2