Skip to content

fix(core): Harden metro dev helpers#6044

Draft
antonis wants to merge 6 commits intomainfrom
fix/metro-dev-helpers-hardening
Draft

fix(core): Harden metro dev helpers#6044
antonis wants to merge 6 commits intomainfrom
fix/metro-dev-helpers-hardening

Conversation

@antonis
Copy link
Copy Markdown
Contributor

@antonis antonis commented Apr 24, 2026

Type of change

  • Bugfix (non-breaking change which fixes an issue)

Description

Two small hardening changes to Metro dev/build-time helpers:

  • metroMiddleware.ts: the source-context middleware resolves frame filenames against the project root (plus any Metro watchFolders), canonicalizes them via fs.realpath, and skips any frame whose canonical path is outside the allowed roots or cannot be resolved. createStackFramesContextMiddleware / createSentryMetroMiddleware take an allowedRoots argument; withSentryMiddleware reads projectRoot and watchFolders from the Metro config.
  • sentryReleaseInjector.ts: use JSON.stringify for the injected name / version values, matching the pattern already used in sentryOptionsSerializer.ts.

Both files are dev/build-time plumbing — no runtime SDK behavior change on end-user devices.

Not addressed here, and why:

  • Binding to localhost instead of 0.0.0.0. Metro — not this middleware — decides the bind address, and physical-device debugging intentionally uses 0.0.0.0.
  • Request-origin checks. Origin headers can be set to anything by a same-LAN attacker, so they don't defend against this threat model. Path validation is the primary defense.

Motivation and Context

Internal security review.

How did you test it?

  • yarn build — succeeds
  • yarn test — all suites pass; added tests for path escape, watchFolders allow-listing, symlink escape via realpath, realpath failure, and JSON escaping in the release injector
  • yarn lint:lerna, yarn circularDepCheck — clean

Checklist

  • I reviewed the code myself
  • I added tests to verify the changes
  • No new linter warnings

Next steps

Follow-up PR for the native getDataFromUri bridge methods after a caller audit.

- Restrict source-context middleware reads to files under the project root.
- Escape release-constants values when injected into the generated bundle.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@antonis
Copy link
Copy Markdown
Contributor Author

antonis commented Apr 24, 2026

@sentry review

@antonis
Copy link
Copy Markdown
Contributor Author

antonis commented Apr 24, 2026

@cursor review

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit ba25101. Configure here.

Monorepos and yarn workspaces set projectRoot to the app package and
declare sibling packages via Metro's watchFolders. Allow reads under any
configured root so source context keeps working in those setups.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@antonis antonis added the ready-to-merge Triggers the full CI test suite label Apr 24, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Android (legacy) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 427.45 ms 424.12 ms -3.33 ms
Size 43.75 MiB 48.15 MiB 4.39 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
4953e94+dirty 442.02 ms 456.52 ms 14.50 ms
2c735cc+dirty 414.09 ms 438.47 ms 24.38 ms
df5d108+dirty 527.06 ms 603.58 ms 76.52 ms
3ce5254+dirty 410.57 ms 448.48 ms 37.91 ms
3d377b5+dirty 406.18 ms 453.52 ms 47.34 ms
0d9949d+dirty 403.57 ms 437.00 ms 33.43 ms
4b87b12+dirty 421.82 ms 413.60 ms -8.22 ms
7ac3378+dirty 404.78 ms 439.84 ms 35.06 ms
890d145+dirty 504.54 ms 491.55 ms -12.99 ms
3817909+dirty 406.67 ms 416.58 ms 9.91 ms

App size

Revision Plain With Sentry Diff
4953e94+dirty 43.75 MiB 48.08 MiB 4.33 MiB
2c735cc+dirty 43.75 MiB 48.08 MiB 4.33 MiB
df5d108+dirty 43.75 MiB 48.08 MiB 4.33 MiB
3ce5254+dirty 43.75 MiB 48.12 MiB 4.37 MiB
3d377b5+dirty 43.75 MiB 48.14 MiB 4.39 MiB
0d9949d+dirty 43.75 MiB 48.13 MiB 4.37 MiB
4b87b12+dirty 43.75 MiB 48.14 MiB 4.39 MiB
7ac3378+dirty 43.75 MiB 48.13 MiB 4.37 MiB
890d145+dirty 43.75 MiB 48.14 MiB 4.39 MiB
3817909+dirty 43.75 MiB 48.08 MiB 4.33 MiB

@sentry
Copy link
Copy Markdown

sentry Bot commented Apr 24, 2026

📲 Install Builds

Android

🔗 App Name App ID Version Configuration
Sentry RN io.sentry.reactnative.sample 8.9.1 (84) Release

⚙️ sentry-react-native Build Distribution Settings

@github-actions
Copy link
Copy Markdown
Contributor

iOS (legacy) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 1231.43 ms 1228.48 ms -2.95 ms
Size 3.38 MiB 4.77 MiB 1.39 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
7ac3378+dirty 1213.37 ms 1218.15 ms 4.78 ms
4b87b12+dirty 1212.90 ms 1222.09 ms 9.19 ms
890d145+dirty 1223.59 ms 1231.37 ms 7.78 ms
0d9949d+dirty 1211.38 ms 1219.67 ms 8.29 ms
04207c4+dirty 1191.27 ms 1189.78 ms -1.48 ms
3ce5254+dirty 1219.93 ms 1221.90 ms 1.96 ms
4953e94+dirty 1212.06 ms 1214.83 ms 2.77 ms
2c735cc+dirty 1229.67 ms 1221.50 ms -8.17 ms
a50b33d+dirty 1197.74 ms 1197.17 ms -0.57 ms
df5d108+dirty 1225.90 ms 1220.14 ms -5.76 ms

App size

Revision Plain With Sentry Diff
7ac3378+dirty 3.38 MiB 4.76 MiB 1.38 MiB
4b87b12+dirty 3.38 MiB 4.77 MiB 1.39 MiB
890d145+dirty 3.38 MiB 4.77 MiB 1.38 MiB
0d9949d+dirty 3.38 MiB 4.76 MiB 1.38 MiB
04207c4+dirty 3.38 MiB 4.76 MiB 1.38 MiB
3ce5254+dirty 3.38 MiB 4.76 MiB 1.38 MiB
4953e94+dirty 3.38 MiB 4.73 MiB 1.35 MiB
2c735cc+dirty 3.38 MiB 4.74 MiB 1.35 MiB
a50b33d+dirty 3.38 MiB 4.73 MiB 1.35 MiB
df5d108+dirty 3.38 MiB 4.73 MiB 1.35 MiB

@github-actions
Copy link
Copy Markdown
Contributor

iOS (new) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 1203.84 ms 1211.32 ms 7.48 ms
Size 3.38 MiB 4.77 MiB 1.39 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
7ac3378+dirty 1202.35 ms 1198.31 ms -4.04 ms
4b87b12+dirty 1199.49 ms 1199.78 ms 0.29 ms
890d145+dirty 1212.98 ms 1220.10 ms 7.12 ms
0d9949d+dirty 1203.94 ms 1202.27 ms -1.67 ms
04207c4+dirty 1228.55 ms 1226.04 ms -2.51 ms
3ce5254+dirty 1217.70 ms 1224.69 ms 6.99 ms
4953e94+dirty 1217.41 ms 1223.53 ms 6.12 ms
2c735cc+dirty 1223.33 ms 1224.38 ms 1.04 ms
a50b33d+dirty 1207.11 ms 1212.10 ms 5.00 ms
df5d108+dirty 1207.34 ms 1210.50 ms 3.16 ms

App size

Revision Plain With Sentry Diff
7ac3378+dirty 3.38 MiB 4.76 MiB 1.38 MiB
4b87b12+dirty 3.38 MiB 4.77 MiB 1.39 MiB
890d145+dirty 3.38 MiB 4.77 MiB 1.38 MiB
0d9949d+dirty 3.38 MiB 4.76 MiB 1.38 MiB
04207c4+dirty 3.38 MiB 4.76 MiB 1.38 MiB
3ce5254+dirty 3.38 MiB 4.76 MiB 1.38 MiB
4953e94+dirty 3.38 MiB 4.73 MiB 1.35 MiB
2c735cc+dirty 3.38 MiB 4.74 MiB 1.35 MiB
a50b33d+dirty 3.38 MiB 4.73 MiB 1.35 MiB
df5d108+dirty 3.38 MiB 4.73 MiB 1.35 MiB

@github-actions
Copy link
Copy Markdown
Contributor

Android (new) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 458.79 ms 532.96 ms 74.17 ms
Size 43.94 MiB 49.00 MiB 5.07 MiB

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
4953e94+dirty 398.80 ms 431.81 ms 33.01 ms
2c735cc+dirty 435.20 ms 459.48 ms 24.28 ms
df5d108+dirty 434.82 ms 447.39 ms 12.57 ms
3ce5254+dirty 373.90 ms 427.84 ms 53.94 ms
3d377b5+dirty 425.38 ms 440.67 ms 15.30 ms
0d9949d+dirty 414.88 ms 428.68 ms 13.81 ms
4b87b12+dirty 356.23 ms 399.86 ms 43.63 ms
7ac3378+dirty 410.67 ms 442.60 ms 31.92 ms
890d145+dirty 486.42 ms 514.85 ms 28.43 ms
3817909+dirty 357.52 ms 391.52 ms 34.00 ms

App size

Revision Plain With Sentry Diff
4953e94+dirty 43.94 MiB 48.94 MiB 5.00 MiB
2c735cc+dirty 43.94 MiB 48.94 MiB 5.00 MiB
df5d108+dirty 43.94 MiB 48.94 MiB 5.00 MiB
3ce5254+dirty 43.94 MiB 48.98 MiB 5.04 MiB
3d377b5+dirty 43.94 MiB 49.00 MiB 5.06 MiB
0d9949d+dirty 43.94 MiB 48.99 MiB 5.05 MiB
4b87b12+dirty 43.94 MiB 49.00 MiB 5.06 MiB
7ac3378+dirty 43.94 MiB 48.99 MiB 5.05 MiB
890d145+dirty 43.94 MiB 49.00 MiB 5.06 MiB
3817909+dirty 43.94 MiB 48.94 MiB 5.00 MiB

@antonis antonis removed the ready-to-merge Triggers the full CI test suite label Apr 24, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 24, 2026

Fails
🚫 Pull request is not ready for merge, please add the "ready-to-merge" label to the pull request

Generated by 🚫 dangerJS against 4e745bd

- metroMiddleware: run realpath on both the allowed roots and each frame
  filename so a symlink inside an allowed root pointing outside cannot
  escape the containment check. Reject frames whose realpath fails.
- sentryReleaseInjector: add a test asserting JSON.stringify escaping,
  so a future refactor cannot silently regress to unescaped interpolation.
- Drop unneeded config cast now that InputConfigT exposes projectRoot
  and watchFolders directly.

Addresses review feedback on #6044.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

1 participant