Skip to content

fix(node): Handle stack traces with data URI filenames #17218

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 31, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion packages/browser/test/tracekit/chromium.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -617,7 +617,7 @@ describe('Tracekit - Chrome Tests', () => {
});
});

it('should drop frames that are over 1kb', () => {
it('should truncate frames that are over 1kb', () => {
const LONG_STR = 'A'.repeat(1040);

const LONG_FRAME = {
Expand All @@ -637,6 +637,12 @@ describe('Tracekit - Chrome Tests', () => {
stacktrace: {
frames: [
{ filename: 'http://localhost:5000/', function: '?', lineno: 50, colno: 19, in_app: true },
{
filename:
'http://localhost:5000/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
function: 'Foo.testMethod',
in_app: true,
},
{ filename: 'http://localhost:5000/', function: 'aha', lineno: 39, colno: 5, in_app: true },
],
},
Expand Down
9 changes: 9 additions & 0 deletions packages/core/src/utils/node-stack-trace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,18 @@ export function filenameIsInApp(filename: string, isNative: boolean = false): bo
export function node(getModule?: GetModuleFn): StackLineParserFn {
const FILENAME_MATCH = /^\s*[-]{4,}$/;
const FULL_MATCH = /at (?:async )?(?:(.+?)\s+\()?(?:(.+):(\d+):(\d+)?|([^)]+))\)?/;
const DATA_URI_MATCH = /at (?:async )?(.+?) \(data:(.*?),/;

// eslint-disable-next-line complexity
return (line: string) => {
const dataUriMatch = line.match(DATA_URI_MATCH);
if (dataUriMatch) {
return {
filename: `<data:${dataUriMatch[2]}>`,
function: dataUriMatch[1],
};
}

const lineMatch = line.match(FULL_MATCH);

if (lineMatch) {
Expand Down
10 changes: 5 additions & 5 deletions packages/core/src/utils/stacktrace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ export function createStackParser(...parsers: StackLineParser[]): StackParser {
const lines = stack.split('\n');

for (let i = skipFirstLines; i < lines.length; i++) {
const line = lines[i] as string;
// Ignore lines over 1kb as they are unlikely to be stack frames.
// Many of the regular expressions use backtracking which results in run time that increases exponentially with
// input size. Huge strings can result in hangs/Denial of Service:
let line = lines[i] as string;
// Truncate lines over 1kb because many of the regular expressions use
// backtracking which results in run time that increases exponentially
// with input size. Huge strings can result in hangs/Denial of Service:
// https://github.com/getsentry/sentry-javascript/issues/2286
if (line.length > 1024) {
continue;
line = line.slice(0, 1024);
}

// https://github.com/getsentry/sentry-javascript/issues/5459
Expand Down
12 changes: 12 additions & 0 deletions packages/core/test/lib/utils/stacktrace.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -380,4 +380,16 @@ describe('node', () => {

expect(node(input)).toEqual(expectedOutput);
});

it('parses function name when filename is a data uri ', () => {
const input =
"at dynamicFn (data:application/javascript,export function dynamicFn() { throw new Error('Error from data-uri module');};:1:38)";

const expectedOutput = {
function: 'dynamicFn',
filename: '<data:application/javascript>',
};

expect(node(input)).toEqual(expectedOutput);
});
});
Loading