Skip to content

Classify Cloudflare bot challenges as upstream_bot_challenge instead of rejected credentials - #2127

Open
mmarabel wants to merge 1 commit into
UsefulSoftwareCo:mainfrom
mmarabel:fix/openapi-cloudflare-challenge-classification
Open

mmarabel wants to merge 1 commit into
UsefulSoftwareCo:mainfrom
mmarabel:fix/openapi-cloudflare-challenge-classification

Conversation

@mmarabel

Copy link
Copy Markdown
Contributor

Summary

An upstream response with cf-mitigated: challenge (Cloudflare's documented challenge signal) now fails as upstream_bot_challenge and carries the Ray ID. Before, it failed as connection_rejected, with a re-authenticate prompt and the challenge page's HTML as details. The edge answered before the request reached the API, so the credential was never checked. OpenAPI health probes now report such a response as degraded, not expired.

  • @executor-js/sdk: adds detectBotChallenge. It checks headers only, and strictly, so a page that merely looks like a challenge never classifies. Also adds botChallengeToolFailure and botChallengeMessage, so every protocol plugin reports the same shape and text: category: "upstream_protection", upstream.{provider, mitigation, rayId}, and recovery guidance that does not suggest a reconnect.
  • OpenAPI: checked before the 401/403 branch for any non-2xx status. Managed challenges are 403; older JS challenges are 503. The health probe returns degraded with reason upstream_status. No new HealthCheckReason literal is added, so nothing changes in the persisted schema.
  • GraphQL: tool invocation is classified the same way. The GraphQL health probe goes through introspection errors, which carry no response headers, so it is unchanged here.
  • No automatic retry. A challenge expects a browser to solve it, and the same request from the same egress gets the same verdict, so retryable: false.

Linked issue

Fixes #2126

Verification

  • bun run format:check

  • bun run lint

  • bun run typecheck (@executor-js/sdk, @executor-js/plugin-openapi, @executor-js/plugin-graphql)

  • bun run test for those packages: sdk 947, plugin-openapi 341, plugin-graphql 119, all passing

  • New tests:

    • core detector and failure shape
    • OpenAPI 403 challenge
    • OpenAPI 503 challenge
    • challenge-looking HTML without the header stays connection_rejected
    • a challenged health probe reads degraded
    • GraphQL 403 challenge

    The three OpenAPI challenge tests fail without the change.

  • Reproduced before the change against a live Cloudflare-fronted API from Executor Cloud (details in [bug] Cloudflare bot challenges are reported as rejected credentials #2126).

  • e2e: not run. This changes error classification only and adds no UI. The result shows through the existing Degraded badge and its detail text.

Checklist

  • Added a changeset (bun run changeset), or this change needs none.
  • Added or updated tests for the new behaviour.
  • No secrets, credentials, or private data in the diff.

…of rejected credentials

A response carrying cf-mitigated: challenge was served by Cloudflare's edge
before the request reached the API, so the credential was never checked.
OpenAPI and GraphQL invocations reported it as connection_rejected with a
re-authenticate prompt and the challenge page's HTML; OpenAPI health probes
marked the connection expired.

Detect the documented header in the SDK and fail such calls as
upstream_bot_challenge with the Ray ID. OpenAPI health probes report the
challenge as degraded.

Fixes UsefulSoftwareCo#2126

This branch has not been deployed

No deployments
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.

[bug] Cloudflare bot challenges are reported as rejected credentials

1 participant