What the check looks at
C5 runs up to three steps against your home page. The worst step decides the result.
- Step 1, cookies on a cached page. Only when your home page is already cached at the edge: the plugin requests it with a fake WordPress login cookie and a WooCommerce cart cookie. A
HITmeans people who carry those cookies get the anonymous copy. - Step 2, a private answer. The plugin requests the home page with a one-time token, and for that request your server sends the headers WordPress sends to signed in users (
nocache_headers()).DYNAMICorBYPASSmeans the edge respected them. A cacheable status means the rule ignores what your server says, so step 3 runs. - Step 3, a private answer with a login cookie. The same with the fake login cookie. If it is still cacheable, nothing stops a signed in page from being stored.
- What PHP sent. For the step 2 request the plugin also reads the
Cache-Controlheader PHP actually sent. Withoutno-store, something on the site removed the header WordPress set.
Like every request Edge Doctor sends, these go only to the hosts of your Site Address and WordPress Address (home_url() and site_url()). An address WordPress gives on another host, such as a single sign on page, is never requested.
Results and what they mean
| Result | What it means |
|---|---|
| PassedConfidence: High | The edge respects what your server says about caching The private answer in step 2 was not cached, and step 1 found nothing. |
| WarningConfidence: High | The edge serves cached pages to people with a cart or a login cookie Step 1: a request with a login or cart cookie was answered from the cache. |
| WarningConfidence: Medium | Your cache rule ignores what your server says about caching Step 3 bypassed the cache thanks to the login cookie, so signed in visitors are protected, but anything else your server marks private is still stored. |
| FailedConfidence: High | A page built for a signed in user can be cached and served to others Step 3: the rule ignores the origin headers and does not step aside for the login cookie either. |
| WarningConfidence: Medium | Something on your site removes the headers WordPress sends to signed in users The steps passed, but the response left PHP without no-store. A theme or plugin is changing the headers. |
| Could not checkConfidence: High | This check could not be completed The cache key ignores the query string, so steps 2 and 3 were not sent ( qs_ignored). |
| Could not checkConfidence: Medium | This check could not be completed The test request never reached your server ( token_missing), or too many checks ran in the last minute (rate_limited). |
| Could not checkConfidence: Low | This check could not be completed The requests did not get through. See the reasons below. |
| Not applicable | Cloudflare is not in front of this site Check A1 did not detect Cloudflare, so this check sent no request. Reason not_behind_cloudflare. |
When the result names a reason
qs_ignored: Your cache key ignores the query string, so the plugin cannot test a page without risking a cached copy of it. Before it asks for any private address, the plugin requests your home page twice with a different unique query string. If either answer is aHIT, your cache key ignores the query string, and a test request could store a private page under an address visitors use. So the plugin stops and sends nothing.token_missing: The test request never reached your server, so there was nothing to compare. On C5 the request was answered without your server seeing it, which happens when something in front of the server answers instead.rate_limited: Too many checks ran in the last minute. Wait a moment and run them again.loopback_failed: Your server could not reach its own site, so this check had nothing to read. The plugin links this result to its own guide: Your server could not reach its own site.blocked_by_config: WordPress itself refused the requests from your site to itself, so none was sent. WP_HTTP_BLOCK_EXTERNAL is on, and your own address is not let through. The plugin links this result to its own guide: WordPress blocks requests to your own site.not_behind_cloudflare: This site is not behind Cloudflare.
Symptoms you may notice
- Signed in users see the logged out version of pages, with an empty cart counter or a login link.
- Visitors who are not signed in see the admin bar or someone else’s name (check C3).
- A shop that worked before a new Cache Rule starts showing wrong carts (check C2).
Why it happens
Cloudflare does not cache responses marked private or no-store by default (Cloudflare: default cache behavior). A Cache Rule whose Edge TTL is Ignore cache-control header and use this TTL means “completely ignore any cache-control header on the response”, so those headers no longer protect anything, and only a cookie condition in the rule is left.
Fake cookies are enough for the test: Cloudflare decides about the cache before WordPress sees the cookie, so the plugin learns how the edge treats a cookie without logging anybody in.
Confirm it by hand
Step 1 by hand: request your home page twice with a login cookie of any value:
curl -sI -H "Cookie: wordpress_logged_in_test=1" "https://example.com/" | grep -iE "cf-cache-status|age"A HIT means the edge served the cached copy to a cookie holder.
Steps 2 and 3 by hand: log in, open your home page with DevTools open (Network, Disable cache ticked) and read the response headers. WordPress 6.8 and later sends signed in users Cache-Control with no-store and private. If cf-cache-status is HIT or MISS, the edge stored a signed in page.
How to fix it
Either change below closes the Failed result; both together are the safer setup.
Let the rule follow your server. In the Cache Rule that covers your HTML, set Edge TTL to Use cache control-header if present, bypass cache if not. On a test site this turned private answers into BYPASS.
Bypass on WordPress and WooCommerce cookies. Make the rule step aside when these cookies are present:
(http.cookie contains "wordpress_logged_in_") or (http.cookie contains "woocommerce_items_in_cart") or (http.cookie contains "wp_woocommerce_session_")In WordPress, for the Warning about removed headers: look for a theme function or a plugin that filters nocache_headers or changes Cache-Control after WordPress sets it.
After a change, purge the cache once so pages stored under the old rule are gone.
Limitations
The test cookies are not valid, so WordPress treats the requests as logged out. The check measures what the edge does with the cookie, not what a real signed in page contains.
Step 1 runs only when your home page is cached at the edge; otherwise there is no cached copy to test against.
The plugin cannot tell where a change to Cache-Control after PHP happened, on the server or at Cloudflare (for example Browser Cache TTL rewriting max-age), so it does not judge that.
Only the home page is tested, through the data center the server’s requests pass through. A rule that matches only some paths can behave differently elsewhere on the site.
Related checks
- C3 Logged-in pages in the public cache: looks for a signed in page that has already leaked.
- C2 WooCommerce cart, checkout and account in the cache: the cart, checkout and account pages.
- C6 Cached pages older than their nonces: cached pages with expired nonces.
- C1 wp-admin and the login page in the cache: wp-admin and the login page.
Sources
- Cloudflare: default cache behavior
- Cloudflare: Cache Rules settings
- Cloudflare: create a Cache Rule
- Cloudflare: http.cookie field
Run this check on your own site with Edge Doctor for Cloudflare®, free on WordPress.org.
Edge Doctor for Cloudflare® is not affiliated with or endorsed by Cloudflare, Inc. Cloudflare is a registered trademark of Cloudflare, Inc.