Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Fix beforeSend and beforeBreadcrumb hooks to preserve original payload on invalid return#48

Merged
neSpecc merged 7 commits intomasterfrom
fix/nodejs-catcher-hook-payload-safety
Feb 11, 2026
Merged

Fix beforeSend and beforeBreadcrumb hooks to preserve original payload on invalid return#48
neSpecc merged 7 commits intomasterfrom
fix/nodejs-catcher-hook-payload-safety

Conversation

@Dobrunia
Copy link
Member

Summary

  • Clone payload/breadcrumb via structuredClone before passing to beforeSend / beforeBreadcrumb hooks, so the original is restored when the hook returns an invalid value or mutates required fields
  • Consolidate multiple null/undefined/invalid branches into a single fallback path with a unified warning message
  • Add message field validation to isValidBreadcrumb (must be a non-empty string), matching isValidEventPayload which already validates title

Copy link
Contributor

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 beforeSend and beforeBreadcrumb hooks so that invalid hook returns (or mutations of required fields) don’t corrupt the original event/breadcrumb being sent/stored.

Changes:

  • Pass a structuredClone of the event/breadcrumb into beforeSend / beforeBreadcrumb and only apply results when validation succeeds.
  • Consolidate the “invalid/no return” cases into a single fallback path with a unified warning message.
  • Extend breadcrumb validation by requiring message to be a non-empty string, and update/expand tests accordingly.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/index.ts Clones payload before beforeSend, validates hook result, and uses unified warning on fallback.
src/modules/breadcrumbs.ts Clones breadcrumb before beforeBreadcrumb, validates hook result (including message), and uses unified warning on fallback.
tests/before-send.test.ts Consolidates invalid-return coverage into parameterized tests and adds mutation/required-field deletion cases.
tests/breadcrumbs.test.ts Consolidates invalid-return coverage into parameterized tests and adds mutation/required-field deletion cases.
package.json Bumps package version to 3.3.2.

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

src/index.ts Outdated
Comment on lines 297 to 298
const eventPayloadClone = structuredClone(payload);
const result = this.beforeSend(eventPayloadClone);
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

structuredClone(payload) can throw (e.g., DataCloneError) if the payload contains non-cloneable values such as functions, class instances with unserializable internals, etc. Since this call is not wrapped, a user-provided beforeSend + custom context/user data could crash error reporting entirely. Consider wrapping the clone in a try/catch and falling back to calling beforeSend with the original payload (or skipping the hook) while still ensuring the original payload is preserved when validation fails.

Copilot uses AI. Check for mistakes.
/**
* Anything else is invalid — warn, payload stays untouched (hook only received a clone)
*/
console.warn('[Hawk] Invalid beforeSend value. It should return event or false. Event is sent without changes.');
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

The warning message says the hook "should return event or false", but the public beforeSend type/documentation explicitly allows returning nothing (void/undefined/null) to keep the original event (with a warning). The current wording is misleading for the undefined/null cases that are treated as an allowed no-op. Update the message to include the "return nothing to keep original" option (and ideally distinguish between "returned nothing" vs "returned invalid value").

Copilot uses AI. Check for mistakes.
Comment on lines 140 to 141
const breadcrumbClone = structuredClone(bc);
const result = this.options.beforeBreadcrumb(breadcrumbClone, hint);
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

structuredClone(bc) can throw (e.g., DataCloneError) if the breadcrumb contains non-cloneable values (commonly via breadcrumb.data). Since this is unhandled, adding a breadcrumb with such data would throw and prevent breadcrumb storage (and potentially affect subsequent error sending). Consider wrapping the clone in try/catch and falling back to passing the original breadcrumb into the hook (or skipping the hook) while keeping the current "restore original on invalid" behavior where possible.

Copilot uses AI. Check for mistakes.
/**
* Anything else is invalid — warn, bc stays untouched (hook only received a clone)
*/
console.warn('[Hawk] Invalid beforeBreadcrumb value. It should return breadcrumb or false. Breadcrumb is stored without changes.');
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

The warning message says the hook "should return breadcrumb or false", but beforeBreadcrumb also supports returning nothing (void/undefined/null) to keep the original breadcrumb (with a warning) per the options docs above. The current wording is misleading for the intentional no-return case; consider updating it to mention that returning nothing keeps the original breadcrumb.

Copilot uses AI. Check for mistakes.
@neSpecc neSpecc merged commit cb7d5c0 into master Feb 11, 2026
2 of 4 checks passed
@neSpecc neSpecc deleted the fix/nodejs-catcher-hook-payload-safety branch February 11, 2026 17:35
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.

3 participants