Skip to content

docs(handoff): the urllib 403 was Cloudflare BIC, not nginx — root-caused, fixed, and the hypothesis retracted - #550

Merged
ZacxDev merged 1 commit into
mainfrom
docs/handoff-403-rootcause
Sep 11, 2026
Merged

docs(handoff): the urllib 403 was Cloudflare BIC, not nginx — root-caused, fixed, and the hypothesis retracted#550
ZacxDev merged 1 commit into
mainfrom
docs/handoff-403-rootcause

Conversation

@ZacxDev

@ZacxDev ZacxDev commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Retires an open investigation whose leading hypothesis was wrong, and records
the measured root cause before it is lost.

The retraction

handoff-agent-setup-onboarding.md has carried, since 2026-09-08:

Leading hypothesis: a UA denylist in the docs repo's own nginx.conf.
Next probe: read the docs PR's report.

That is refuted. The block is left intact and a ✅ RESOLVED block added above
it — a corrected reading is worth more than a deleted one — but its "Next probe"
is explicitly marked do-not-run.

Root cause: Cloudflare Browser Integrity Check

Not the origin, not the docs repo. Evidence:

  • GraphQL firewallEventsAdaptiveaction=block source=bic ruleId=bic
  • block body 17 B, text/plain: error code: 1010 (BIC's error code)
  • the 403 carried none of the origin's headers (etag,
    x-content-type-options, cf-cache-status); the 200 carried all three

Fixed by a Configuration Rule (http.host eq "developer.civitai.com")
set_config {"bic": false}. browser_check stays on zone-wide, so
civitai.com and image.civitai.com keep BIC.

Verified by content, not status: Python-urllib/3.12 now receives
byte-identical bytes to a known-good UA on /, /index.html, /llms.txt,
/apps/ and /agent-setup/prompt.md (6,949 B and 13,066 B, cmp clean).

Gotchas recorded

  • A Page Rule target without a trailing * matches one path — the first
    attempt fixed / and nothing else, which reads as "the rule didn't work".
  • PUT /zones/{z}/rulesets/{id} replaces the whole rules array, and the
    official docs only demonstrate PUT. This zone has 5 other Configuration Rules.
  • A Configuration Rule does override the zone-level browser_check — and no
    Cloudflare doc says so
    ; confirmed empirically instead.
  • The BIC denylist is exact-string, case-sensitive, undocumented and mostly porous
    (empty UA → 200, Wget → 200), so "document a UA requirement" was never a fix.
  • A pagerules GET without the scope returns .result: null — read as a count it
    gives a confident 0 for a zone with 13. Check .success first.

Also recorded in the subsystem index as cli/agent-setup (rev 00077c780e37edea),
which outlives this doc.

Docs only. buckets: were APPEND-only, so no other section of the doc was touched.

@ZacxDev
ZacxDev merged commit 1123812 into main Sep 11, 2026
13 checks passed
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