Skip to content

[Bug]: HTTP reverse proxy swallows OPTIONS requests — breaks CORS preflight for extensions #7324

@0xtlt

Description

@0xtlt

Problem

The HTTP reverse proxy used by shopify app dev intercepts OPTIONS requests
and never forwards them to the target application. This breaks CORS preflight
for any cross-origin call made from UI extensions (e.g. Customer Account
extensions calling the app backend through the Cloudflare tunnel).

The root cause is in packages/app/src/cli/utilities/app/http-reverse-proxy.ts:
the proxy forwards every method but does not handle OPTIONS specially, and
http-proxy silently drops the preflight — the request never reaches the
user's app, so no CORS headers are returned.

Expected behavior

An OPTIONS preflight request to the tunnel URL should either:

  • be forwarded to the target app so it can respond with its own CORS headers, or
  • be answered at the proxy level with correct CORS headers.

Actual behavior

The OPTIONS request gets a response with no CORS headers (no
Access-Control-Allow-Origin, etc.). The browser then blocks the actual
request. The request never appears in the app's logs.

Reproduction

  1. Run shopify app dev (any backend — Express, Remix, etc.)
  2. From an extension (or curl):
    curl -i -X OPTIONS \
      -H "Origin: https://extensions.shopifycdn.com" \
      -H "Access-Control-Request-Method: GET" \
      https://<tunnel>.trycloudflare.com/any-path
  3. Response has no CORS headers → browser blocks the follow-up request.

Opening the tunnel directly with cloudflared tunnel --url … works fine,
confirming the issue is in the CLI's reverse proxy, not Cloudflare.

Impact

Any extension that makes a cross-origin fetch to the app backend during local
dev is affected. Common case: Customer Account UI extensions calling app API
routes.

Related

Environment

  • OS: macOS
  • Shopify CLI: 3.x
  • Node: 22.x

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions