News
ETag vs Cache-Control for Personalized Pages
August 28, 2023
ETag vs Cache-Control for personalized pages is a byte validator versus who may store the response. Cache-Control (private, no-store, no-cache) says whether a shared CDN may keep the HTML. An ETag is a validator for later If-None-Match revalidation. A user-specific page with Cache-Control: public and a stable ETag is how one person's dashboard can be served to the next. Cookies on the response without private/no-store is the same class. RoastMyOpsec inspects Cache-Control versus Set-Cookie on the landing HTML. It does not score ETag, does not send If-None-Match as a poisoning test, and does not brute-force validators.
The practical difference
Cache-Control is policy: public, private, max-age, no-store. ETag is a name for a body version. Strong ETags mean byte-identical. Weak ETags (W/) mean semantically close. Neither header authenticates the user. Authorization still belongs in the app.
Static marketing assets want public plus ETag or hashed filenames. Account HTML wants no-store or private plus Vary: Cookie (and usually no shared ETag that ignores the session).
How to choose validators
Public immutable assets: long max-age, filename hash, ETag optional. Personalized HTML: Cache-Control: private, no-store (or max-age=0, must-revalidate with private) and do not let the CDN cache by URL only. If you must revalidate, the ETag must not be identical across users for the same URL. See Cache-Control public vs private.
| Page type | Cache-Control | ETag role | Takeaway |
|---|---|---|---|
| Hashed JS/CSS | public, max-age long, immutable | Optional; filename already unique | Share freely |
| Marketing HTML | public with a short max-age, or CDN TTL | Fine if the body is the same for everyone | No Set-Cookie on that response |
| Logged-in HTML | private, no-store (or equivalent) | Must not be a shared user-agnostic tag | The miss if public + cookie |
| API JSON with cookies | private / no-store | Same rule | See CORS + cookies separately |
What the roast can prove
Set-Cookie plus a public cache directive on the landing response can surface. A present ETag is not a finding. Confirm CDN keys include cookie or authorization where the body varies. Pair with HttpOnly cookies if the personalized page also sets a session.
Common mistakes
The first mistake is CDN cache-everything on /dashboard.
The second mistake is a inode-based ETag that is identical for every user of the same template.
The third mistake is treating ETag as an access-control header.
Free audit the URL you own
RoastMyOpsec is a defensive public-surface roast: headers, cookies, sensitive paths, and more — no exploit payloads. Start with the free audit, then open the vault if the blurred findings look expensive.
Free audit nowFAQ
- Is an ETag a vulnerability?
- Not by itself. A shared cache key plus a user-specific body is. Fix Cache-Control and the CDN key.
- Should I remove ETags everywhere?
- No. Static assets benefit. Personalized HTML should not be publicly cacheable whether or not an ETag exists.
- Does RoastMyOpsec score ETag?
- No. It compares Cache-Control to Set-Cookie on the landing response. No cache-poisoning tests.