[wp-trac] [WordPress Trac] #63636: Enable instant page navigations from browser history via bfcache when sending "nocache" headers
WordPress Trac
noreply at wordpress.org
Wed Aug 27 14:48:43 UTC 2025
#63636: Enable instant page navigations from browser history via bfcache when
sending "nocache" headers
-------------------------------------------------+-------------------------
Reporter: westonruter | Owner:
| westonruter
Type: enhancement | Status: accepted
Priority: normal | Milestone: 6.9
Component: Administration | Version: 6.3
Severity: normal | Resolution:
Keywords: has-patch dev-feedback needs-unit- | Focuses:
tests | performance, privacy
-------------------------------------------------+-------------------------
Comment (by kkmuffme):
1) Since the function is called "wp_get_nocache_headers()" I'd expect that
there should be absolutely no caching including no bfcache be happening.
This is why "no-store" should stay included.
Instead, maybe create a "wp_get_only_bfcache_headers()" (or whatever makes
sense) which excludes "no-store" and uses "private" only.
2) In an ideal world it's +100 from me :-)
However:
The problem with those headers is always that proxy caches change if/which
directives they adhere to and how.
Theoretically, you're right that according to
https://datatracker.ietf.org/doc/html/rfc7234 just setting "private"
without no-store should be enough to ensure it's not stored in any proxy
caches.
Unfortunately, it is not in practice:
https://developers.cloudflare.com/cache/concepts/cache-control/#conditions
>Cache-Control returned to eyeball does not include private.
This means that suddenly it's Cache-Control without no-store and without
private.
Now it might happen that max-age is ignored too e.g. due to account
limitations at the Edge (e.g.
https://developers.cloudflare.com/cache/concepts/cache-
control/#expiration) and you'll suddenly end up serving private, non-
cacheable data to everybody.
Fyi: what's in Cloudflare's docs and what is actually happening is often 2
very different things that may also change without any notice from my
experience working closely with Cloudflare's caches for a decade now.
While I wish this was a theoretical assumption only, it's been something
that has been exploited a couple years back with some cache plugins/CDNs.
Since WP is used behind all kinds of set-ups, the only absolutely safe way
is to actually always use both - no-store, private - for pages that are at
risk of replay attacks (especially since WP's nonce, isn't a real nonce
that can only be used once) and/or pages that contain private data.
3) the bfcache introduces a huge potential for data loss for data that can
be used by multiple users (= anything in wp-admin)
e.g. user A opens page 123, then navigates to page 456.
User B changes the title of 123 from "Hello" to "World"
User A clicks the browser back button - it will show title 123 "Hello" -
if the user now clicks "Update", it will restore the old title again.
This is bc https://web.dev/articles/bfcache
>Note that when a page is restored from bfcache, it is restored from
memory, not from the HTTP cache. As a result, directives like Cache-
Control: no-cache or Cache-Control: max-age=0 are not taken into account,
and no revalidation occurs before the content is displayed to the user.
Fyi Chrome is implementing this natively:
https://developer.chrome.com/docs/web-platform/bfcache-ccns
Also see https://github.com/whatwg/html/issues/7189
--
Ticket URL: <https://core.trac.wordpress.org/ticket/63636#comment:10>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform
More information about the wp-trac
mailing list