Skip to content

fix: break cloudflare managed challenge loop#1065

Draft
lidel wants to merge 3 commits into
mainfrom
fix/strip-cf-challenge-params-at-edge
Draft

fix: break cloudflare managed challenge loop#1065
lidel wants to merge 3 commits into
mainfrom
fix/strip-cf-challenge-params-at-edge

Conversation

@lidel

@lidel lidel commented May 14, 2026

Copy link
Copy Markdown
Member

Note

This is not critical, but nice-to-have if we want to limit inbrowser.link/dev to real humans.

Problem

I did a test with Managed Challenge on inbrowser.dev to curb non-human traffic (AI crawlers pretending to be browsers etc).

Visitors were getting an infinite Cloudflare challenge. After passing the challenge, Cloudflare sends you to /?__cf_chl_tk=<one-time-token> but injected JS has not oportunity to strip it. The service worker installer on that page reloads the URL to take over, Cloudflare sees the already-used token a second time, assumes buggy bot and serves a fresh challenge. Repeat.

This made me disable managed challenge for all on inbrowser.dev for now.

Solution

The Cloudflare snippet (02) now strips every __cf_* query param at the edge and 302s to the clean URL, so the token is consumed once and the app never sees it.

Two related cleanups, one commit each:

  • snippet 02 caches only 2xx. unexpected 3xx , or Cloudflare's own 403 challenge response, no longer land in the installer cache. feels safer, protects us from misconfigurations (ours or Cloudflare's)
  • snippet 01 caches its path-to-subdomain 301 at the edge via caches.default, with the same __cf_* strip so any per-visitor tracking tokens share one cache entry instead of fragmenting it.
    • we do not see many 301 right now, but as people start using inbrowser.link/ipfs/{cid} more often, the redirect to subdomain could cost us meaningful cache misses

Testing

Once deployed to inbrowser.dev, we can enable managed challenge for all Security Rule for inbrowser.dev to see if infinite loop is gone, and HTTP 301s get cached

lidel added 3 commits May 14, 2026 22:22
Cloudflare's Managed Challenge lands the visitor on a URL with a
single-use __cf_chl_tk token. The SW installer reloads that URL,
Cloudflare sees the replayed token, and challenges again. Strip every
__cf_* param at the edge and 302 to the clean URL so reloads and
shared links no longer carry challenge state.
Origin returns 200 for every SPA route via the _redirects rewrite, so
3xx is anomalous. The 4xx/5xx exclusion also keeps Cloudflare's own
challenge response (403 with cf-mitigated: challenge) out of the
normalized cache key.
The /ipfs/ and /ipns/ to subdomain mapping is deterministic, but the
synthesized 301 never hit the edge cache. Cache it via caches.default
keyed by source URL so repeat hits skip CID parsing and multibase
decode.

Strip __cf_* params before keying the cache and the Location so
per-visitor challenge tokens share one cache entry and never leak
onto the subdomain (snippet 02 would otherwise strip them in a
second hop).
@lidel lidel requested a review from achingbrain May 14, 2026 20:57
@lidel lidel marked this pull request as draft May 19, 2026 14:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant