Security Auditor — verifies the signed key directory at
/.well-known/http-message-signatures-directory that origins such as Cloudflare use to recognise your bot.Bot verification
Cloudflare Verified Bots and any RFC 9421 verifier look up your public keys in this directory before trusting your crawler.
Signed directory
The directory response itself must be signed by each key it publishes, with a short, unexpired validity window.
How it works
The auditor ports the checks of Cloudflare’shttp-signature-directory validator:
- Locate — builds
<scheme>://<host>/.well-known/http-message-signatures-directoryfrom the audited URL (its path is ignored) and fetches it withAccept: application/http-message-signatures-directory+json, following redirects. - Blocked or missing — HTTP 403, 429 or a Cloudflare challenge ends the run as a blocked bot (
590). Any other non-2xx status fails (400): a bot owner without a reachable directory cannot be verified. - Keys — parses the body as a JWKS. Each key must be an
OKPkey on curveEd25519with a 32-byte base64urlx. The RFC 7638 thumbprint of each key is thekeyidverifiers expect. - Signatures — reads
Signature-InputandSignature. For every key there must be an entry withtag="http-message-signatures-directory",keyidequal to the thumbprint,created,expiresand the("@authority";req)component. The entry must not be expired, and the Ed25519 signature must verify over the RFC 9421 signature base built from the final response URL. - Hygiene — warns when the directory is served over
http, with the wrongContent-Type, or with aCache-Controllifetime longer than the signature’s remaining validity (a cached copy would be served with an expired signature). - Aggregate —
ERRORwins, thenFAIL, thenWARNING; if every rule passes, the audit isSUCCESS. - Specification pin — every run emits
37A-WebBotAuthAuditor-100(INFORMATION) naming draft-meunier-http-message-signatures-directory-03 and RFC 9421. That check does not change overall status.
What it audits
Every row maps to onecheckRule* method and one CheckCode. 37A-WebBotAuthAuditor-100 is emitted on every run, including fetch errors. Key rules (403–409) run once per published key, so one audit can carry several checks with the same code. 401 skips every later FAIL rule; 402 skips the key rules; a key that fails 403 or 404 skips 406–409; 405 skips 406–409 for all keys; 406 skips 407–409 for that key; 407 skips 408 and 409. CheckCode suffixes use status ranges: 100 information, 200 success, 300–399 warning, 400–499 fail, 500–599 error.
Output documentation
Risks and considerations
An unverifiable bot is an anonymous bot
- Cloudflare and other origins verify your crawler by fetching this directory and checking the signature on it. A missing, unsigned or expired directory makes every signed request from your bot look unverified, and bot protection treats it like any unknown crawler.
- Rotate keys by publishing the old and the new key together, each with its own directory signature, until the bot has switched.
Caching silently breaks signed directories
- The directory response is signed with a
created/expireswindow. A CDN, framework cache or static export that serves the same response pastexpireshands verifiers an expired signature. Sign on every request, or keep the cache lifetime below the validity window.
What this auditor does not check
- The bot’s own signed requests (
tag="web-bot-auth", theSignature-Agentheader) leave the bot, not the site, so they cannot be audited from the outside. Use Cloudflare’scrawltest.comto test those. - The
content-digestcomponent the draft recommends is not required; Cloudflare’s validator does not require it either. - Registration with Cloudflare Verified Bots is a separate submission and is not verified.