Skip to content

Conversation

s1gr1d
Copy link
Member

@s1gr1d s1gr1d commented Aug 6, 2025

The injected code snippets where changed in those PRs:

This PR adds a try/catch guard around the snippet to avoid errors.

closes #782

Copy link
Member

@Lms24 Lms24 left a comment

Choose a reason for hiding this comment

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

Which issue does this close? The "closes" currently just links to a previous PR :)

Also, I thought the snippet was safe enough to avoid the size hit of the try/catch but chances are high I missed something. So I think we should proceed with this PR.

@@ -431,7 +431,7 @@ export function createComponentNameAnnotateHooks(ignoredComponents?: string[]):
}

export function getDebugIdSnippet(debugId: string): string {
return `;{try{(function(){var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="${debugId}",e._sentryDebugIdIdentifier="sentry-dbid-${debugId}");})();}catch(e){}};`;
return `;{try{(function(){var e=("undefined"!=typeof window&&window)||("undefined"!=typeof global&&global)||("undefined"!=typeof globalThis&&globalThis)||("undefined"!=typeof self&&self)||{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="${debugId}",e._sentryDebugIdIdentifier="sentry-dbid-${debugId}");})();}catch(e){}};`;
Copy link
Member

Choose a reason for hiding this comment

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

what was the concern with the ternary chain here? Isn't it smaller in bundle size?

@s1gr1d s1gr1d force-pushed the sig/add-try-catch branch from 77bf77d to 06d6a99 Compare August 7, 2025 09:13
Comment on lines +338 to +340
return `!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{};e._sentryModuleMetadata=e._sentryModuleMetadata||{},e._sentryModuleMetadata[(new e.Error).stack]=function(e){for(var n=1;n<arguments.length;n++){var a=arguments[n];if(null!=a)for(var t in a)a.hasOwnProperty(t)&&(e[t]=a[t])}return e}({},e._sentryModuleMetadata[(new e.Error).stack],${JSON.stringify(
metadata
)})}();`;
)})}catch(e){}}();`;

Check warning

Code scanning / CodeQL

Improper code sanitization Medium

Code construction depends on an
improperly sanitized value
.

Copilot Autofix

AI 26 days ago

To fix the problem, we need to ensure that any stringified object injected into generated JavaScript code is properly sanitized to prevent code injection, especially if the code is ever embedded in an HTML <script> tag. The best way to do this is to escape potentially dangerous characters in the output of JSON.stringify(metadata) before inserting it into the code string. This can be achieved by defining an escapeUnsafeChars function (as shown in the background) and applying it to the result of JSON.stringify(metadata). The changes should be made in packages/bundler-plugin-core/src/utils.ts:

  • Add the escapeUnsafeChars function and its supporting charMap near the top of the file.
  • In generateModuleMetadataInjectorCode, replace JSON.stringify(metadata) with escapeUnsafeChars(JSON.stringify(metadata)).

Suggested changeset 1
packages/bundler-plugin-core/src/utils.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/packages/bundler-plugin-core/src/utils.ts b/packages/bundler-plugin-core/src/utils.ts
--- a/packages/bundler-plugin-core/src/utils.ts
+++ b/packages/bundler-plugin-core/src/utils.ts
@@ -8,2 +8,22 @@
 
+// Escape potentially dangerous characters for safe code injection
+const charMap: Record<string, string> = {
+  '<': '\\u003C',
+  '>': '\\u003E',
+  '/': '\\u002F',
+  '\\': '\\\\',
+  '\b': '\\b',
+  '\f': '\\f',
+  '\n': '\\n',
+  '\r': '\\r',
+  '\t': '\\t',
+  '\0': '\\0',
+  '\u2028': '\\u2028',
+  '\u2029': '\\u2029'
+};
+
+function escapeUnsafeChars(str: string): string {
+  return str.replace(/[<>\b\f\n\r\t\0\u2028\u2029/\\]/g, x => charMap[x] || x);
+}
+
 /**
@@ -337,4 +357,4 @@
   // Use try-catch to avoid issues when bundlers rename global variables like 'window' to 'k'
-  return `!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{};e._sentryModuleMetadata=e._sentryModuleMetadata||{},e._sentryModuleMetadata[(new e.Error).stack]=function(e){for(var n=1;n<arguments.length;n++){var a=arguments[n];if(null!=a)for(var t in a)a.hasOwnProperty(t)&&(e[t]=a[t])}return e}({},e._sentryModuleMetadata[(new e.Error).stack],${JSON.stringify(
-    metadata
+  return `!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{};e._sentryModuleMetadata=e._sentryModuleMetadata||{},e._sentryModuleMetadata[(new e.Error).stack]=function(e){for(var n=1;n<arguments.length;n++){var a=arguments[n];if(null!=a)for(var t in a)a.hasOwnProperty(t)&&(e[t]=a[t])}return e}({},e._sentryModuleMetadata[(new e.Error).stack],${escapeUnsafeChars(
+    JSON.stringify(metadata)
   )})}catch(e){}}();`;
EOF
@@ -8,2 +8,22 @@

// Escape potentially dangerous characters for safe code injection
const charMap: Record<string, string> = {
'<': '\\u003C',
'>': '\\u003E',
'/': '\\u002F',
'\\': '\\\\',
'\b': '\\b',
'\f': '\\f',
'\n': '\\n',
'\r': '\\r',
'\t': '\\t',
'\0': '\\0',
'\u2028': '\\u2028',
'\u2029': '\\u2029'
};

function escapeUnsafeChars(str: string): string {
return str.replace(/[<>\b\f\n\r\t\0\u2028\u2029/\\]/g, x => charMap[x] || x);
}

/**
@@ -337,4 +357,4 @@
// Use try-catch to avoid issues when bundlers rename global variables like 'window' to 'k'
return `!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{};e._sentryModuleMetadata=e._sentryModuleMetadata||{},e._sentryModuleMetadata[(new e.Error).stack]=function(e){for(var n=1;n<arguments.length;n++){var a=arguments[n];if(null!=a)for(var t in a)a.hasOwnProperty(t)&&(e[t]=a[t])}return e}({},e._sentryModuleMetadata[(new e.Error).stack],${JSON.stringify(
metadata
return `!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{};e._sentryModuleMetadata=e._sentryModuleMetadata||{},e._sentryModuleMetadata[(new e.Error).stack]=function(e){for(var n=1;n<arguments.length;n++){var a=arguments[n];if(null!=a)for(var t in a)a.hasOwnProperty(t)&&(e[t]=a[t])}return e}({},e._sentryModuleMetadata[(new e.Error).stack],${escapeUnsafeChars(
JSON.stringify(metadata)
)})}catch(e){}}();`;
Copilot is powered by AI and may make mistakes. Always verify output.
@s1gr1d s1gr1d merged commit c1441e8 into main Aug 8, 2025
39 of 40 checks passed
@s1gr1d s1gr1d deleted the sig/add-try-catch branch August 8, 2025 08:25
@Lms24
Copy link
Member

Lms24 commented Aug 8, 2025

I think it was fine to add the guards here but I don't understand how typeof k would throw an error, even if k is undefined. So something feels off all together but let's not worry about it 😅

@s1gr1d
Copy link
Member Author

s1gr1d commented Aug 8, 2025

Yeah, I'm also not 100% sure about this specific case but adding a try/catch here is a good idea in general.

renovate bot added a commit to andrei-picus-tink/auto-renovate that referenced this pull request Aug 12, 2025
| datasource | package             | from  | to    |
| ---------- | ------------------- | ----- | ----- |
| npm        | @sentry/vite-plugin | 3.6.1 | 4.1.0 |


## [v4.1.0](https://github.com/getsentry/sentry-javascript-bundler-plugins/blob/HEAD/CHANGELOG.md#410)

- feat(deps): Bump [@sentry/cli](https://github.com/sentry/cli) to 2.51.0 [#786](getsentry/sentry-javascript-bundler-plugins#786)
- feat(core): Add flag for disabling sourcemaps upload [#785](getsentry/sentry-javascript-bundler-plugins#785)
- fix(debugId): Add guards for injected code to avoid errors [#783](getsentry/sentry-javascript-bundler-plugins#783)
- docs(options): Improve JSDoc for options [#781](getsentry/sentry-javascript-bundler-plugins#781)
- feat(core): Expose method for injecting debug Ids from plugin manager [#784](getsentry/sentry-javascript-bundler-plugins#784)


## [v4.0.2](https://github.com/getsentry/sentry-javascript-bundler-plugins/blob/HEAD/CHANGELOG.md#402)

- fix(core): Make `moduleMetadata` injection snippet ES5-compliant ([#774](getsentry/sentry-javascript-bundler-plugins#774))


## [v4.0.1](https://github.com/getsentry/sentry-javascript-bundler-plugins/blob/HEAD/CHANGELOG.md#401)

- fix(core): Make plugin inject ES5-friendly code ([#770](getsentry/sentry-javascript-bundler-plugins#770))
- fix(core): Use `renderChunk` for release injection for Rollup/Rolldown/Vite ([#761](getsentry/sentry-javascript-bundler-plugins#761))

Work in this release was contributed by [@grushetsky](https://github.com/grushetsky). Thank you for your contribution!


## [v4.0.0](https://github.com/getsentry/sentry-javascript-bundler-plugins/blob/HEAD/CHANGELOG.md#400)

##### Breaking Changes

- (Type change) Vite plugin now returns `VitePlugin` type instead of `any`
- Deprecated function `getBuildInformation` has been removed

##### List of Changes

- feat(core)!: Remove `getBuildInformation` export ([#765](getsentry/sentry-javascript-bundler-plugins#765))
- feat(vite)!: Update return type of vite plugin ([#728](getsentry/sentry-javascript-bundler-plugins#728))
renovate bot added a commit to andrei-picus-tink/auto-renovate that referenced this pull request Aug 15, 2025
| datasource | package             | from  | to    |
| ---------- | ------------------- | ----- | ----- |
| npm        | @sentry/vite-plugin | 3.6.1 | 4.1.1 |


## [v4.1.1](https://github.com/getsentry/sentry-javascript-bundler-plugins/blob/HEAD/CHANGELOG.md#411)

- fix(react-native): Enhance fragment detection for indirect references ([#767](getsentry/sentry-javascript-bundler-plugins#767))


## [v4.1.0](https://github.com/getsentry/sentry-javascript-bundler-plugins/blob/HEAD/CHANGELOG.md#410)

- feat(deps): Bump [@sentry/cli](https://github.com/sentry/cli) to 2.51.0 [#786](getsentry/sentry-javascript-bundler-plugins#786)
- feat(core): Add flag for disabling sourcemaps upload [#785](getsentry/sentry-javascript-bundler-plugins#785)
- fix(debugId): Add guards for injected code to avoid errors [#783](getsentry/sentry-javascript-bundler-plugins#783)
- docs(options): Improve JSDoc for options [#781](getsentry/sentry-javascript-bundler-plugins#781)
- feat(core): Expose method for injecting debug Ids from plugin manager [#784](getsentry/sentry-javascript-bundler-plugins#784)


## [v4.0.2](https://github.com/getsentry/sentry-javascript-bundler-plugins/blob/HEAD/CHANGELOG.md#402)

- fix(core): Make `moduleMetadata` injection snippet ES5-compliant ([#774](getsentry/sentry-javascript-bundler-plugins#774))


## [v4.0.1](https://github.com/getsentry/sentry-javascript-bundler-plugins/blob/HEAD/CHANGELOG.md#401)

- fix(core): Make plugin inject ES5-friendly code ([#770](getsentry/sentry-javascript-bundler-plugins#770))
- fix(core): Use `renderChunk` for release injection for Rollup/Rolldown/Vite ([#761](getsentry/sentry-javascript-bundler-plugins#761))

Work in this release was contributed by [@grushetsky](https://github.com/grushetsky). Thank you for your contribution!


## [v4.0.0](https://github.com/getsentry/sentry-javascript-bundler-plugins/blob/HEAD/CHANGELOG.md#400)

##### Breaking Changes

- (Type change) Vite plugin now returns `VitePlugin` type instead of `any`
- Deprecated function `getBuildInformation` has been removed

##### List of Changes

- feat(core)!: Remove `getBuildInformation` export ([#765](getsentry/sentry-javascript-bundler-plugins#765))
- feat(vite)!: Update return type of vite plugin ([#728](getsentry/sentry-javascript-bundler-plugins#728))
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.

Runtime errors after upgrading to @sentry/[email protected]
3 participants