From c57d0ed3969fcb47abdd48a187138c1dae2137eb Mon Sep 17 00:00:00 2001 From: Kiril Kirov Date: Tue, 6 Oct 2026 10:17:09 +0000 Subject: [PATCH] fix(core): stop reading a form Turnstile loader as a bot wall A readable storefront that loads the Turnstile api.js for its forms still drew three findings. cart-handoff-reachability now fails only a cart that is a challenge page or only a widget. no-bot-detection passes a loader on a page the scan could read. no-blocking-captcha matches vendor script src and widget elements instead of the vendor name, so inline config, CSP lists and prose no longer match. --- .changeset/turnstile-form-scope.md | 5 +++ .../access-crawl-control/no-bot-detection.md | 12 ++++++ .../cart-handoff-reachability.md | 16 ++++++++ .../operability-safety/no-blocking-captcha.md | 20 ++++++++++ .../no-bot-detection.test.ts | 17 ++++++++ .../access-crawl-control/no-bot-detection.ts | 34 +++++++++++++--- .../cart-handoff-reachability.test.ts | 40 ++++++++++++++++++- .../cart-handoff-reachability.ts | 22 +++++++++- .../no-blocking-captcha.test.ts | 31 ++++++++++++++ .../operability-safety/no-blocking-captcha.ts | 27 ++++++++----- .../real-page-corpus.test.ts.snap | 30 +++++++------- 11 files changed, 218 insertions(+), 36 deletions(-) create mode 100644 .changeset/turnstile-form-scope.md diff --git a/.changeset/turnstile-form-scope.md b/.changeset/turnstile-form-scope.md new file mode 100644 index 00000000..8e3387bc --- /dev/null +++ b/.changeset/turnstile-form-scope.md @@ -0,0 +1,5 @@ +--- +"@forkpoint/agent-lighthouse-core": patch +--- + +Stop treating a Cloudflare Turnstile loader on a readable page as a bot wall. `agentic-commerce/cart-handoff-reachability` fails only a cart that is a challenge page or only a widget, `access-crawl-control/no-bot-detection` passes a loader on a page the scan could read, and `operability-safety/no-blocking-captcha` matches widget scripts and markup instead of any mention of the vendor name. diff --git a/docs/evidence/audits/access-crawl-control/no-bot-detection.md b/docs/evidence/audits/access-crawl-control/no-bot-detection.md index b234412f..db24f139 100644 --- a/docs/evidence/audits/access-crawl-control/no-bot-detection.md +++ b/docs/evidence/audits/access-crawl-control/no-bot-detection.md @@ -82,6 +82,18 @@ a pause is the only way to get a verdict from a rate-limited origin. ## Implementation deviations +### A loader on a readable page passes (2026-10-06) + +The page-script branch warned at weight 1 on any page whose HTML contained a +challenge host, including `challenges.cloudflare.com`. The counter-evidence +grades that sub-signal D, and the required fix says to warn only when the +widget gates the main content. A loader is now reported only on a page that +served no readable text, using the per-page `renderedByPage` verdict from the +scan evidence (`pageRendersText` when it is absent). A loader on a page the +scan read is named in a pass, because no wall was observed and the page was +read. The `wafProtection` branch, which carries the A grade, is unchanged. +Script-`src` scoping and a UA probe are still open items from the review above. + - 2026-10-06 — the shared WAF detector no longer treats the `challenges.cloudflare.com` hostname as proof of an access wall. A live fetch of a storefront returned HTTP 200 with the storefront HTML and a diff --git a/docs/evidence/audits/agentic-commerce/cart-handoff-reachability.md b/docs/evidence/audits/agentic-commerce/cart-handoff-reachability.md index 085e108c..55250001 100644 --- a/docs/evidence/audits/agentic-commerce/cart-handoff-reachability.md +++ b/docs/evidence/audits/agentic-commerce/cart-handoff-reachability.md @@ -73,6 +73,22 @@ Tier per evidence policy: **scored** — grade B meets the A/B bar required for - **Without a platform fingerprint the audit is not applicable, not failing.** It still probes `/cart` and `/checkout`, but when neither answers it reports `notApplicable`: the paths were a guess. With a fingerprint, an unanswered cart path is a failure, because the platform's own convention says where it should be. - **The JS-only arm needs both halves.** A document warns only when its visible text is under 200 characters _and_ it carries no `