SkillByAIOpen interactive version →

Lesson 23 / 25

Caching and Security

Avoid leaking private data and defend against cache poisoning and deception.

Caches can leak and be poisoned

Caching mistakes can expose one user's data to another. Caching private responses in shared caches is the classic bug: an account page served with public caching, or a CDN rule "cache everything" applied to authenticated paths, can show Asha's details to the next visitor. Mark personalised responses private or no-store, and keep CDN rules from caching authenticated routes. Web cache deception tricks a cache into storing a private page by requesting it with a static-looking suffix, such as /account/profile.css, which some caching rules treat as a static file while the application still returns the profile. Defend by caching based on response headers and content types rather than URL extensions alone, and by having the application return 404 for unexpected paths. Web cache poisoning exploits inputs that affect the response but are not part of the cache key (unkeyed headers such as X-Forwarded-Host); an attacker gets a malicious variant cached for everyone. Defend by not reflecting unkeyed inputs, and by including in the key every input that changes the response.

Safe and unsafe response headers

The first response would leak a private page through a shared cache.

# DANGEROUS: personalised page marked public
GET /account HTTP/1.1
Cookie: session=abc

HTTP/1.1 200 OK
Cache-Control: public, max-age=600          # a CDN may serve this to other users

# SAFE
HTTP/1.1 200 OK
Cache-Control: private, no-store
Vary: Cookie                                 # extra protection for misconfigured caches

A shared notice board

A CDN is a notice board in the building lobby. Pinning a public timetable there is great; pinning someone's bank statement because it looked like a timetable is a disaster.

Quick check: What is the most important header setting for a personalised account page?

  • Cache-Control: public, max-age=3600
  • Cache-Control: private or no-store
  • Cache-Control: s-maxage=600
  • Vary: User-Agent only
Answer

Cache-Control: private or no-store — Personalised responses must never be stored in shared caches.