[DO NOT MERGE] feat(core): add opt-in assertion instrumentation - #6592
[DO NOT MERGE] feat(core): add opt-in assertion instrumentation#6592antonis wants to merge 11 commits into
8 issues
Medium
Unvalidated `rethrowPragmas` option can crash Babel on malformed config - `packages/core/src/js/tools/sentryAssertionBabelPlugin.ts:567-568`
Add a defensive Array.isArray(options.rethrowPragmas) check before calling .includes() — a non-array value (e.g., a string passed via Metro config) causes a build-time TypeError.
Module-level reportedSites set is never reset between tests - `packages/core/test/assertion.test.ts:24-27`
beforeEach clears mocks but leaves the module-level reportedSites set intact, so tests that pass siteId pollute shared state and can flake in watch mode.
Unbounded values iteration in flattenValues allows DoS via large objects - `packages/core/src/js/assertion.ts:225-237`
flattenValues iterates over every key in values without a count cap and calls JSON.stringify(values) on the full object before truncation, allowing a large input object to exhaust CPU and memory.
collectValueIdentifiers bypasses TDZ guard when AST nodes lack location info - `packages/core/src/js/tools/sentryAssertionBabelPlugin.ts:327-334`
When the assertion condition node has no start (e.g., synthesized by an earlier Babel plugin), the TDZ guard in collectValueIdentifiers is skipped entirely and textually-after let/const bindings are captured. Reading them on the report path crashes with a ReferenceError.
ensureErrorBinding alias crashes when globalThis is shadowed by const/let - `packages/core/src/js/tools/sentryAssertionBabelPlugin.ts:483-490`
The hoisted var _Error initializer can throw a ReferenceError if the module contains a const globalThis or let globalThis declaration, because typeof on a TDZ binding throws instead of returning 'undefined'.
Low
Overly broad node_modules path detection may skip first-party files - `packages/core/src/js/tools/sentryAssertionBabelPlugin.ts:359`
filename.includes('node_modules') matches any path containing that substring, so a first-party file whose path happens to contain node_modules (e.g., node_modules_helper.js or a node_modules_workspace/ directory) can be incorrectly treated as a dependency and skipped when includeNodeModules is false or absent. This contradicts the stated intent that first-party code is instrumented by default.
Error alias fallback can throw ReferenceError in TDZ on pre-globalThis runtimes - `packages/core/src/js/tools/sentryAssertionBabelPlugin.ts:485`
The hoisted Error alias falls back to bare Error when globalThis is absent. On ES6–ES2019 runtimes that support let/const TDZ but lack globalThis, a module-level let Error causes the fallback to throw ReferenceError instead of creating the alias.
Module-level `reportedSites` set in `captureAssertionViolation` has no size bound, risking memory exhaustion with dynamic `siteId` values - `packages/core/test/integrations/reactnativeerrorhandlers.test.ts:211`
captureAssertionViolation uses a module-level Set (reportedSites) that only grows and is never cleared or capped. While the Babel transform generates static siteId values (filename:line:column) that are bounded by the number of assertion call sites, the function is also a public API exported from @sentry/react-native. A manual caller passing dynamically-generated siteId strings with once: true (the default) can cause the set to grow without bound over the lifetime of the JS runtime, leading to gradual memory exhaustion.
Also found at:
packages/core/test/tools/sentryAssertionBabelPlugin.test.ts:104
4 skills analyzed
| Skill | Findings | Duration | Cost |
|---|---|---|---|
| security-review | 0 | 3m 46s | $1.63 |
| code-review | 4 | 31m 24s | $3.98 |
| find-bugs | 4 | 37m 12s | $9.83 |
| gha-security-review | 0 | 33m 20s | $0.10 |
⏱ 105m 42s · 18.1M in / 1.0M out · $15.54