[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