Skip to content

Add cross-origin guard to community-cli-plugin dev server - #59661

Open
huntie wants to merge 1 commit into
pr59316from
pr59661
Open

huntie wants to merge 1 commit into
pr59316from
pr59661

Conversation

@huntie

@huntie huntie commented Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Context

Migration of the remaining core dev server endpoints from @react-native-community/cli-server-api into core (community-cli-plugin).

Core motivation: These endpoints are critical infra! Most notably the WS /message endpoint, which carries reload and Dev Menu commands from the terminal and other tools.

The intent is to later move most of these again into dev-middleware (shared by CLI and Expo). For now, this stack focuses on decoupling CLI as an initial migration. (I note also that fb-metro-cli probably can't accept moving all of these into dev-middleware just yet.)

This diff

Add a guard that refuses cross-origin browser requests before any route handles them, and mount the plugin's middleware ahead of the Community CLI's so the guard covers its routes too.

What the guard does

For each HTTP request:

  • No Origin header (curl, native apps, Node): passes through.
  • Origin is the dev server's own origin, a local hostname (localhost, 127.0.0.1, 0.0.0.0, [::]) on any port, or Chrome DevTools (devtools://devtools): passes through.
  • Any other Origin: responds 403 and stops, so no route runs.
  • Every response that passes sets X-Content-Type-Options: nosniff.

It applies to every HTTP route mounted after it, including /open-stack-frame, /open-url, the CLI's remaining routes and Metro's. It does not apply to WebSocket upgrades.

Paired with react-native-community/cli#2877, which removes the CLI's copies.

Net changes

This is a non-breaking change when CLI and react-native are shipped in lockstep.

  • Replaces the CLI's guard, which allowed only the configured host (localhost by default) and answered other origins with a 500.
  • Remove the origin checks from /open-stack-frame and /open-url, which the guard now covers.
  • Compress responses and disable caching for everything mounted behind the guard, as the CLI's middleware did.

Changelog: [Internal]

Test Plan

yarn jest packages/community-cli-plugin/src/dev-server

✅ 29 tests pass, covering the accepted and refused origins and a cross-origin request refused before any route. Flow and ESLint clean.

✅ RNTester's Metro with this stack: a cross-origin Origin on a Metro bundle URL gets 403, and http://localhost:3000 passes with nosniff.

✅ Behind the guard, /debugger-frontend/rn_fusebox.html answers 200 and /json/list lists the RNTester target.

@huntie
huntie changed the base branch from main to pr59316 October 30, 2026 11:10
@huntie
huntie added this pull request to stack #59664 October 30, 2026 11:11
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Oct 30, 2026
@huntie
huntie marked this pull request as ready for review October 30, 2026 11:46

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

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. p: Expo Partner: Expo Partner

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant