Consent decision stored and respected on subsequent visits
Why it matters
Under GDPR Art. 7(1), the controller must be able to demonstrate that consent was obtained — which presupposes that the consent decision is durably stored. If consent is written to sessionStorage instead of localStorage or a first-party cookie, the banner reappears on every new browser session, which undermines CCPA §1798.135's opt-out persistence requirement and forces users to re-engage with the consent mechanism repeatedly. ePrivacy Art. 5(3) additionally requires that access to stored information only occur after consent is obtained — storing consent in a mechanism that doesn't survive the session means scripts fire on the very next load.
Severity rationale
High because session-only consent storage causes the consent mechanism to functionally reset on every new tab or browser restart, making sustained lawful processing impossible under GDPR Art. 7 and ePrivacy Art. 5(3).
Remediation
Write consent to localStorage (or a first-party cookie with a multi-year max-age) and include a version field to support re-consent when the cookie inventory changes. The initialization useEffect must read this value and only show the banner when nothing is stored or the version has changed.
// src/lib/consent.ts
const CONSENT_KEY = 'cookie_consent'
const CONSENT_VERSION = '1.0' // bump to trigger re-consent
export type ConsentState = {
necessary: true
analytics: boolean
marketing: boolean
timestamp: string
version: string
}
export function needsConsent(): boolean {
if (typeof window === 'undefined') return false
const raw = localStorage.getItem(CONSENT_KEY)
if (!raw) return true
try {
const stored = JSON.parse(raw) as ConsentState
return stored.version !== CONSENT_VERSION
} catch { return true }
}
export function saveConsent(state: Omit<ConsentState, 'necessary' | 'timestamp' | 'version'>): void {
localStorage.setItem(CONSENT_KEY, JSON.stringify({
necessary: true, ...state,
timestamp: new Date().toISOString(),
version: CONSENT_VERSION,
}))
}
Call needsConsent() in the banner's useEffect. Never use sessionStorage as the sole storage mechanism.
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 Cookie & Consent Compliance Audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
External references
- gdpr · Art. 7(1) — GDPR — controller must demonstrate consent was obtained
- eprivacy · Art. 5(3) — ePrivacy Directive — consent must persist across sessions
- ccpa · §1798.135 — CCPA — opt-out preference must be honored on return visits
Taxons
History
- 2026-04-18·v1.0.0·Initial import from cookie-consent-compliance·automated