What the check looks at
C1 asks for two addresses with a unique query parameter and no cookies: wp-admin and the login page, both as WordPress itself gives them (admin_url() and wp_login_url()). It reads cf-cache-status on each, and the worst answer decides.
Because WordPress gives the address, a login page that a security plugin moved through the WordPress filters login_url or site_url, as WPS Hide Login does, is measured where it is. The report page in your admin shows that address in full. The report you copy, the printout and wp edge-doctor --redact show it as [custom login URL], so you can share the report without giving the address away. A login page hidden in a way WordPress does not know about is never guessed.
The login page counts only when it is confirmed: a 200 answer with the form WordPress itself prints (id="loginform" in a body with the classes login and login-action-login). A form alone is not enough, because themes print the same form elsewhere. When the login address redirects once to wp-login.php or to the login path on your own site, the plugin follows that one redirect and nothing else.
When WordPress gives wp-admin or the login page on another host, for example a single sign on page on another domain or the www form of your domain, the plugin does not ask for it. It measures wp-admin/ and wp-login.php on your own site instead and says so in a note. A wp-login.php that redirects to a sign on page on another host is not followed, so the login page is not confirmed.
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
The plugin sorts the cf-cache-status header Cloudflare returns into classes. HIT, MISS, EXPIRED, STALE, REVALIDATED and UPDATING all mean the response was eligible for the cache, so they count as cacheable; a MISS is a copy that is being stored now. BYPASS means a rule made the request eligible, but the origin response was not cacheable. DYNAMIC means Cloudflare decided at request time that the response is not eligible, which is the normal state for private pages. (Cloudflare: cache responses.)
| Result | What it means |
|---|---|
| PassedConfidence: High | Your admin pages are not cached Cloudflare treats wp-admin and the login page as dynamic. |
| WarningConfidence: High | A cache rule reaches your admin pages A rule covers wp-admin or the login page and is bypassing the cache for now ( BYPASS). Only the headers your server sends keep them out. |
| FailedConfidence: High | Cloudflare is caching your admin pages Cloudflare answered for wp-admin or the confirmed login page from its cache, or stored it. |
| Could not checkConfidence: High | This check could not be completed The cache key ignores the query string, so nothing was requested ( qs_ignored). |
| Could not checkConfidence: Medium | This check could not be completed wp-admin was fine, but the login page could not be confirmed: a password prompt, maintenance, a Cloudflare challenge or Access sign in, or a page that does not answer with the login form WordPress prints. |
| Could not checkConfidence: Low | This check could not be completed Cloudflare did not say what it did, or the requests did not get through. |
| 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 wp-admin is cached or reached by a rule, that result stands even if the login page could not be confirmed; the reason for the login page then becomes a note.
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.login_not_found: The login page did not answer at wp-login.php, so it could not be checked. Its address has probably been changed, often by a security plugin. Since version 1.0.1 the plugin checks the login address WordPress gives, so this sentence means that this address, too, could not be confirmed as the login page. The plugin links this result to its own guide: The login page could not be confirmed.basic_auth: The site asks for a password at the server level, which a scheduled run cannot answer. The login address answered 401.maintenance: The site is in maintenance mode or behind a coming soon page, so the pages read were not the real ones. The login address answered 503.edge_challenge: Cloudflare answered the plugin with a challenge or a sign in page instead of the page, so it could not be read. The checks for requests from your server to itself report this. Check E1 or E2 tells you what Cloudflare is doing there.worker: A Cloudflare Worker sits in front of this site, so cache headers do not say what the cache did.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
- After logging in you see the login form again, or a dashboard that does not match your account.
- Someone else sees an admin screen they should never see.
- Login fails with an expired or invalid form token.
Why it happens
Cloudflare does not cache HTML by default (Cloudflare: default cache behavior). A Cache Rule that makes all HTML eligible for the cache, written for the whole site, also covers wp-admin and the login page unless it excludes them. With BYPASS the rule reaches them but the headers WordPress sends keep them out; a change at either end could start caching them.
Confirm it by hand
Request both addresses without cookies. If a security plugin moved your login page, use that address instead of wp-login.php:
curl -sI "https://example.com/wp-login.php?cachetest=1" | grep -iE "cf-cache-status|cache-control"
curl -sI "https://example.com/wp-admin/?cachetest=1" | grep -iE "cf-cache-status|cache-control"DYNAMIC is what you want; BYPASS is the Warning; HIT or MISS means the address is cacheable.
How to fix it
In Cloudflare: narrow the Cache Rule so it does not cover wp-admin and the login page at all, for example by adding to its expression (add your own login path if it was moved):
and not (http.request.uri.path contains "/wp-admin" or http.request.uri.path contains "/wp-login.php")Then purge the cache once.
In WordPress: nothing to change for the cache.
Limitations
A login page hidden without telling WordPress, so that wp_login_url() does not return it, is not searched for. The plugin reports login_not_found rather than guess its address.
An address WordPress gives on another host is not requested. The plugin measures the default address on your own site, which may not be the page your users sign in on.
The requests carry no cookies, so a rule that caches only for some cookies is covered by check C5 instead.
Related checks
- C5 Login cookies and private responses: how the cache treats login cookies.
- C2 WooCommerce cart, checkout and account in the cache: the same test for shop pages.
- E1 Cloudflare blocking your own server: challenges on requests from your server.
- E2 Cloudflare Access in front of admin-ajax.php: Cloudflare Access on admin addresses.
Sources
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.