fix: limit outgoing webhook response size to prevent memory exhaustion#38760
Conversation
|
Looks like this PR is not ready to merge, because of the following issues:
Please fix the issues and try again If you have any trouble, please check the PR guidelines |
🦋 Changeset detectedLatest commit: c78fc78 The changes in this PR will be included in the next version bump. This PR includes changesets to release 41 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
WalkthroughAdded a 10MB ( Changes
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~2 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
apps/meteor/app/integrations/server/lib/triggerHandler.ts (1)
622-622: Extract the 20 MB magic number to a named constant.♻️ Proposed refactor
+const MAX_WEBHOOK_RESPONSE_SIZE_BYTES = 20 * 1024 * 1024; // 20 MB fetch( opts.url, { method: opts.method, headers: opts.headers, ...(opts.timeout && { timeout: opts.timeout }), ...(opts.data && { body: opts.data }), - size: 20 * 1024 * 1024, + size: MAX_WEBHOOK_RESPONSE_SIZE_BYTES, }, settings.get('Allow_Invalid_SelfSigned_Certs'), )🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/meteor/app/integrations/server/lib/triggerHandler.ts` at line 622, Replace the magic literal "20 * 1024 * 1024" used for the size option with a named constant (e.g., MAX_ATTACHMENT_SIZE_BYTES or MAX_PAYLOAD_SIZE_BYTES) declared at the top of the module (or an appropriate constants file) and reference that constant where the code currently sets "size: 20 * 1024 * 1024" in triggerHandler.ts; ensure the constant name clearly indicates bytes and update any other identical magic-number occurrences in the file to use the same constant.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
apps/meteor/app/integrations/server/lib/triggerHandler.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)
**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation
Files:
apps/meteor/app/integrations/server/lib/triggerHandler.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: cubic · AI code reviewer
🔇 Additional comments (1)
apps/meteor/app/integrations/server/lib/triggerHandler.ts (1)
615-623: Thesizeoption is properly supported. The@rocket.chat/server-fetchpackage explicitly usesnode-fetchv2.7.0, and theExtendedFetchOptionstype includessize?: numberwhich is passed through to the underlying fetch call viaparseRequestOptions. The fix will work as intended.However, the generic error handler at line 786 doesn't distinguish a size limit exceeded error from other network errors. Consider adding explicit handling for the
max-sizeerror type to provide better observability:.catch(async (err) => { + if (err?.type === 'max-size') { + outgoingLogger.warn({ msg: 'Integration response exceeded size limit', integrationName: trigger.name, url }); + } else { outgoingLogger.error({ err }); + } await updateHistory({ historyId, step: 'after-http-call', httpError: err, httpResult: null, }); });Additionally, consider extracting the magic number
20 * 1024 * 1024to a named constant for clarity and maintainability.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@apps/meteor/app/integrations/server/lib/triggerHandler.ts`:
- Line 622: Replace the magic literal "20 * 1024 * 1024" used for the size
option with a named constant (e.g., MAX_ATTACHMENT_SIZE_BYTES or
MAX_PAYLOAD_SIZE_BYTES) declared at the top of the module (or an appropriate
constants file) and reference that constant where the code currently sets "size:
20 * 1024 * 1024" in triggerHandler.ts; ensure the constant name clearly
indicates bytes and update any other identical magic-number occurrences in the
file to use the same constant.
a67ed32 to
35e0290
Compare
|
PR is ready for review |
35e0290 to
3108c1d
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
.changeset/shiny-pears-admire.mdapps/meteor/app/integrations/server/lib/triggerHandler.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- apps/meteor/app/integrations/server/lib/triggerHandler.ts
🔇 Additional comments (2)
.changeset/shiny-pears-admire.md (2)
7-7: Error handling exists for the FetchError from the size limit.The
fetchcall at line 615-627 is properly wrapped with a.catch()block (lines 788-796) that handles any errors thrown bynode-fetch, including theFetchErrorwithtype: 'max-size'when the 10MB size limit is exceeded. The error is logged viaoutgoingLogger.error()and recorded in the integration history, preventing an unhandled rejection.Likely an incorrect or invalid review comment.
7-7: Thesizeoption is properly supported.triggerHandler.tsuses@rocket.chat/server-fetch, which wrapsnode-fetch 2.7.0—not the Node.js globalfetch(undici). Thenode-fetchlibrary fully supports thesizeoption for limiting response body size. The option is defined inExtendedFetchOptions, passed throughparseRequestOptions()without filtering, and spreads into the underlyingfetch()call. The 10MB size limit in the changeset is effectively enforced.Likely an incorrect or invalid review comment.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.changeset/shiny-pears-admire.md:
- Around line 5-7: The changeset and code disagree on the outgoing webhook
response cap (changeset uses 10MB while the PR description/issue state 20MB);
pick the intended limit and make it consistent across the project by updating
the .changeset/shiny-pears-admire.md text and the constant/setting in
triggerHandler.ts (e.g., OUTGOING_WEBHOOK_MAX_RESPONSE_SIZE or any local numeric
literal used to enforce the limit) to the chosen value, and also update any
related comments/tests/README entries so all references match the same size
(either 10MB or 20MB).
|
@KevLehman I have made the requested changes |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #38760 +/- ##
===========================================
+ Coverage 70.55% 70.59% +0.03%
===========================================
Files 3189 3189
Lines 112703 112703
Branches 20429 20390 -39
===========================================
+ Hits 79519 79559 +40
+ Misses 31123 31086 -37
+ Partials 2061 2058 -3
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
|
Thanks @KevLehman for the review and getting this merged :) |
|
You're welcome, thx for the good work :) |
Proposed changes (including videos or screenshots)
Enforced a 10MB size limit on the
fetchrequest for Outgoing Webhooks intriggerHandler.tsCurrently, the
triggerHandler.tsfetches webhook responses without specifying asizelimit. If an integration endpoint returns an unexpectedly large response (e.g., infinite stream or large file), the Node.js process attempts to buffer the entire content into memory usingres.text(). This leads to a (OOM) crash and terminates the server.Before (Buggy)
Screencast.from.2026-02-18.02-34-22.mp4
After (fixed)
Screencast.from.2026-02-18.02-27-25.mp4
Issue(s)
Fixes #38758
COMM-144
Further comments
I chose 10MB as the limit because standard JSON payloads for webhooks are typically much smaller (<1MB). This limit allows for legitimate large responses while sufficiently protecting the server from OOM exploits or misconfigurations.
Summary by CodeRabbit