Edge caching strategy handles personalized content
Why it matters
CWE-525 (Information Exposure Through Browser Caching) is the formal classification, but the concrete failure is simpler: if a user-specific API response is cached at the CDN edge without Cache-Control: private, the next user who hits the same edge node may receive another user's private data. This is a data-exposure bug masquerading as a caching misconfiguration. ISO 25010:2011 time-behaviour flags the caching intent; the security consequence is personally identifiable or account-sensitive data served cross-user from an edge cache.
Severity rationale
Medium because edge-caching personalized data exposes user-specific information to other users, but exploitation requires the attacker to hit the same edge node shortly after the victim — reducing but not eliminating real-world risk.
Remediation
Every API route that returns user-specific data must set Cache-Control: private, no-cache. Verify this is applied at the route level, not overridden by a global CDN header rule.
// app/api/user/profile/route.ts
export async function GET(request: Request) {
const profile = await getUserProfile(request)
return Response.json(profile, {
headers: { 'Cache-Control': 'private, no-cache' },
})
}
Detection
-
ID:
edge-cache-personalization -
Severity:
medium -
What to look for: Count all API endpoints returning personalized/user-specific data. Enumerate their Cache-Control headers. Examine API endpoints and data-fetching patterns for personalized content (user-specific dashboards, profiles, private data). Check whether these endpoints are excluded from CDN caching via
Cache-Control: privateor other mechanisms. -
Pass criteria: Personalized/authenticated endpoints use
Cache-Control: privateor are not cached at all. Public content is cached at edge. Browser cache and edge cache strategies are separated. 100% of personalized endpoints must useCache-Control: private. -
Fail criteria: Personalized endpoints are cached at edge without user differentiation, causing one user's data to be served to another. Or all endpoints use the same caching strategy regardless of personalization.
-
Skip (N/A) when: The application has no personalized content or all content is behind authentication.
-
Cross-reference: For stale-while-revalidate on public endpoints, see
stale-while-revalidate-apis. -
Detail on fail:
"User dashboard endpoints cached with Cache-Control: public — user A's data served to user B from edge cache"or"All endpoints use same max-age=600 regardless of whether they are public or user-specific" -
Remediation: Mark personalized content as non-cacheable at edge using
Cache-Control: private, no-cache.// app/api/user/dashboard/route.ts — private cache return Response.json(userData, { headers: { 'Cache-Control': 'private, no-cache' } })
External references
- cwe · CWE-525 — Use of Web Browser Cache Containing Sensitive Information
- iso-25010:2011 · time-behaviour — Time Behaviour (performance efficiency)
Taxons
History
- 2026-04-18·v1.0.0·Initial import from performance-deep-dive·automated