Skip to content

Move /open-stack-frame and /open-url into community-cli-plugin - #59316

Draft
huntie wants to merge 1 commit into
mainfrom
pr59316
Draft

huntie wants to merge 1 commit into
mainfrom
pr59316

Conversation

@huntie

@huntie huntie commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Context

Migrating the remaining core dev server endpoints from @react-native-community/cli-server-api into core (@react-native/community-cli-plugin), so the Community CLI no longer serves them.

This diff

/open-stack-frame and /open-url, which LogBox, RedBox and the new app screen call to open a stack frame in the editor or a docs link in the browser, are served only by @react-native-community/cli-server-api, so the dev server depends on the Community CLI for them. The CLI's stack frame handler also opens any path on disk.

This diff moves both routes into @react-native/community-cli-plugin, mounted by the start command's dev server, and ports the hardening Expo applied to its own /open-stack-frame (expo/expo#44039, expo/expo#45863). The plugin is a halfway house: the routes leave the CLI now, and can lift into @react-native/dev-middleware once Expo adopts them, with that API designed against Expo's needs.

Changes

  • Validate the posted frame, and open only a file that resolves inside the server root or a watch folder, through launch-editor and $REACT_EDITOR as in the CLI.
  • Validate the posted URL: http: or https: only, with none of the characters PowerShell expands, since open launches through a PowerShell string on Windows (CVE-2025-11953).
  • Throttle each route to one launch per 2 seconds, and refuse cross-origin browser requests with the inspector proxy's origin rule.

Notes

Changelog:
[General][Changed] - Dev server: /open-stack-frame opens only files inside the project watch folders and /open-url only http(s) URLs, both served by @react-native/community-cli-plugin

Test Plan

yarn jest packages/community-cli-plugin/src/dev-server
yarn flow-check
yarn eslint packages/community-cli-plugin

✅ 47 tests pass: launches with the posted file and line or URL, same-origin, other local and cross-origin requests, malformed bodies, containment (.., a symlink out, a nonexistent file, a watch folder itself), rejected URL schemes and shell characters, the throttles, a failed browser launch, a GET passing through, and a response an earlier middleware already sent. Flow and ESLint clean.

RNTester's Metro with a local cli-server-api carrying react-native-community/cli#2875 linked in, so the plugin serves both routes, and $REACT_EDITOR set to a script that logs each launch:

  • ✅ curl -X POST /open-stack-frame for RNTesterAppShared.js answered 200 OK and the script logged the file. For /etc/hosts: 400, "File is missing or outside the project watch folders".
  • ✅ curl -X POST /open-url with http://localhost:<port>/status answered 200 OK and opened the browser. For file:///etc/passwd: 400.
  • A cross-origin Origin header is answered by the CLI's own guard, mounted first, with its 500.

Not run on this revision: tapping a LogBox frame on a simulator, which the previous revision ran with the same handler logic.

@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 21, 2026
@huntie huntie changed the title Move /open-stack-frame into dev-middleware Move /open-stack-frame and /open-url into community-cli-plugin Oct 29, 2026

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