feat(playground): Open Sentry in desktop browser from Expo apps#5947
feat(playground): Open Sentry in desktop browser from Expo apps#5947
Conversation
Semver Impact of This PR⚪ None (no version bump detected) 📋 Changelog PreviewThis is how your changes will appear in the changelog.
🤖 This preview updates automatically when you update the PR. |
|
|
Thank you for the PR! and for the video reproduction! I only have one concern in regard to the security of the feature. |
| return; | ||
| } | ||
|
|
||
| if (!url.startsWith('https://') && !url.startsWith('http://')) { |
There was a problem hiding this comment.
I'd only allow requests that has the host sentry.io to avoid any malicious code invoking any kind of url with this method.
This impact self-hosted users, but it's worth the risk,
There was a problem hiding this comment.
I wonder what's the best way to approach that. Technically we shouldn't exclude those using self-hosted Sentry.
There was a problem hiding this comment.
An idea: if the host is not sentry.io then instead of automatically opening the link gets printed to the console with the note that you should only open it if you trust the host (so we basically jump to what's on lines 58-61)
There was a problem hiding this comment.
Good catch @lucas-zimerman and thank you for the suggestion @alwx 🙇
Applied it with ec8663b
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
- Return 405 for non-POST requests instead of hanging - Validate URL scheme (http/https only) - Improve error messages when `open` package is unavailable - Fix inconsistent oxlint disable comments - Add tests for openURLMiddleware and open-url routing Co-Authored-By: Krystof Woldrich <krystofwoldrich@gmail.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Only the derived constants are used externally.
For non-sentry.io hosts, the URL is printed to the Metro console instead of being opened automatically, so users can decide whether to trust it. This prevents the middleware from being used to open arbitrary URLs while still supporting all *.sentry.io subdomains. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Handle both CJS and ESM exports from the `open` package (v8+ is
ESM-only and `require` returns `{ default: fn }` instead of `fn`)
- Sanitize URLs before logging to prevent terminal escape sequence
injection via control characters
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5e430de to
c4514ee
Compare
Android (legacy) Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 4953e94+dirty | 442.02 ms | 456.52 ms | 14.50 ms |
| df5d108+dirty | 527.06 ms | 603.58 ms | 76.52 ms |
| a50b33d+dirty | 500.81 ms | 532.11 ms | 31.30 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 4953e94+dirty | 43.75 MiB | 48.08 MiB | 4.33 MiB |
| df5d108+dirty | 43.75 MiB | 48.08 MiB | 4.33 MiB |
| a50b33d+dirty | 43.75 MiB | 48.08 MiB | 4.33 MiB |
iOS (legacy) Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| df5d108+dirty | 1225.90 ms | 1220.14 ms | -5.76 ms |
| 4953e94+dirty | 1212.06 ms | 1214.83 ms | 2.77 ms |
| a50b33d+dirty | 1197.74 ms | 1197.17 ms | -0.57 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| df5d108+dirty | 3.38 MiB | 4.73 MiB | 1.35 MiB |
| 4953e94+dirty | 3.38 MiB | 4.73 MiB | 1.35 MiB |
| a50b33d+dirty | 3.38 MiB | 4.73 MiB | 1.35 MiB |

📢 Type of change
📜 Description
Previously, the "Open Sentry" button in the Sentry Playground was hidden for Expo-based apps because it relied on the React Native CLI's
open-urlendpoint, which is not available in Expo's Metro setup.This PR adds a custom
/__sentry/open-urlendpoint to the Sentry Metro Middleware. The Playground now sends a POST request to this endpoint, and the middleware uses theopennpm package (available transitively via@react-native-community/cli-server-apiand@expo/cli) to open the URL in the desktop browser.Changes
New files in
packages/core/src/js/metro/:constants.ts— shared path constants (__sentry/context,__sentry/open-url) extracted frommetroMiddleware.tsgetRawBody.ts— request body reader extracted frommetroMiddleware.tsopenUrlMiddleware.ts— new middleware handler for/__sentry/open-urlopenUrlInBrowser.ts— client-side helper that sends the open-url request to the Metro dev serverModified files:
metroMiddleware.ts— routes/__sentry/open-urlto the new middleware, uses extracted constants andgetRawBodyplayground/modal.tsx— removes theisExpo()gate on the "Open Sentry" button, uses the newopenUrlInBrowserhelper instead of the inline function that hit the RN CLI endpointSecurity hardening
http://andhttps://URL schemes are allowed (rejectsfile://,ssh://, etc.)openpackage is unavailable💡 Motivation and Context
Continues the work from #4918 by @krystofwoldrich. The original commit is cherry-picked to preserve attribution.
The Sentry Playground's "Open Sentry" button is useful for verifying SDK setup, but it was only functional in bare React Native apps. Expo users — a large portion of the RN community — couldn't use this feature because Expo doesn't expose the RN CLI's
open-urlmiddleware.💚 How did you test it?
openURLMiddleware(7 tests covering all paths: 405, 400, scheme validation, success, failure)/__sentry/open-urlincreateSentryMetroMiddlewarecurl -X POST http://localhost:8081/__sentry/open-url -d '{"url":"https://sentry-sdks.sentry.io/issues/"}'— URL opened in desktop browserScreen.Recording.2026-04-01.at.14.03.59.mov
📝 Checklist
sendDefaultPIIis enabled🔮 Next steps