Skip to content

fix(core): handle JSON.parse errors in page callback and DevTools handlers#398

Open
lawrence3699 wants to merge 1 commit intoulixee:mainfrom
lawrence3699:fix/unhandled-json-parse
Open

fix(core): handle JSON.parse errors in page callback and DevTools handlers#398
lawrence3699 wants to merge 1 commit intoulixee:mainfrom
lawrence3699:fix/unhandled-json-parse

Conversation

@lawrence3699
Copy link
Copy Markdown

Summary

Noticed two places where JSON.parse() is called on external data without try-catch, which can crash the session if the payload is malformed:

  1. Tab.onPageCallback() in core/lib/Tab.tsJSON.parse(payload) is called directly on the page callback event payload from injected scripts. If a page sends a malformed callback (e.g., during a navigation race or from a misbehaving script), the unhandled SyntaxError crashes the DOM recorder event handling for that tab. Added try-catch with a warning log that includes the sessionId, frameId, and payload for debugging, matching the existing pattern used in getElementHtml() and other methods in the same file.

  2. Connection.onMessage() in agent/main/lib/Connection.tsJSON.parse(message) on incoming DevTools WebSocket messages has no error handling. While the protocol typically sends valid JSON, transport issues (partial messages, connection resets mid-frame) can produce malformed data. An unhandled exception here tears down the entire browser connection. Added try-catch with a truncated message log (capped at 500 chars to avoid log bloat), consistent with the existing log.warn pattern used for unknown sessions in the same method.

Test plan

  • Verify malformed page callback payloads are logged and skipped instead of crashing
  • Verify malformed DevTools messages are logged and skipped instead of tearing down the connection
  • Existing tests still pass

…dlers

Wrap unprotected JSON.parse calls in onPageCallback and Connection.onMessage
with try-catch to prevent malformed payloads from crashing the session.
Copilot AI review requested due to automatic review settings April 2, 2026 10:43
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR hardens the session against malformed external JSON inputs by preventing unhandled exceptions from JSON.parse() in two event-handling paths (page callback payloads and DevTools transport messages).

Changes:

  • Wrap JSON.parse(payload) in Tab.onPageCallback with try/catch and skip invalid payloads with a warning log.
  • Wrap JSON.parse(message) in Connection.onMessage with try/catch and skip invalid DevTools messages with a warning log (message truncated to 500 chars).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
core/lib/Tab.ts Adds parse error handling and warning logging for injected page callback payloads.
agent/main/lib/Connection.ts Adds parse error handling and warning logging for incoming DevTools transport messages.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +940 to +945
log.warn('Tab.onPageCallback:InvalidPayload', {
sessionId: this.sessionId,
frameId,
payload,
error,
});
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

payload for page recorder events can be very large (and may include DOM content). Logging the full raw payload on parse failure risks log bloat and potential data exposure. Consider truncating the payload (and optionally include payloadLength) similar to the 500-char cap used for DevTools messages.

Copilot uses AI. Check for mistakes.
error,
});
return;
}
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

Catching JSON.parse errors prevents SyntaxErrors, but parseable non-conforming JSON (e.g., null, a number, or an unexpected object) will still be passed into onPageRecorderEvents and can throw (it assumes an array-of-arrays). Add a lightweight shape/type check (eg, Array.isArray(parsedPayload) and expected length) and warn+return when invalid.

Suggested change
}
}
// Validate payload shape: expect an array-of-arrays.
const isValidArrayOfArrays =
Array.isArray(parsedPayload) && parsedPayload.every(item => Array.isArray(item));
if (!isValidArrayOfArrays) {
log.warn('Tab.onPageCallback:InvalidPayloadShape', {
sessionId: this.sessionId,
frameId,
payload,
});
return;
}

Copilot uses AI. Check for mistakes.
error,
});
return;
}
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

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

JSON.parse can succeed but return a non-object (eg, null, a number, an array). In that case object.timestamp = ... will throw and still tear down the connection. After parsing, add a guard that object is a non-null plain object before mutating/reading fields; otherwise log+return.

Suggested change
}
}
if (
typeof object !== 'object' ||
object === null ||
Array.isArray(object)
) {
log.warn('Connection.InvalidMessageType', {
sessionId: null,
message: message.slice(0, 500),
parsedType: typeof object,
});
return;
}

Copilot uses AI. Check for mistakes.
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.

2 participants