Limit webhook request body size with http.MaxBytesReader#995
Limit webhook request body size with http.MaxBytesReader#995nevyangelova wants to merge 1 commit intomasterfrom
Conversation
📝 WalkthroughWalkthroughAdded a 25 MB size limit to webhook request bodies in the handler using Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
server/plugin/webhook_test.go (1)
33-77: Use the production limit constant and add exact-boundary coverage.Line 46 hardcodes
26*1024*1024. PrefermaxWebhookPayloadSize+1, and add a subtest for exactlymaxWebhookPayloadSizeto prevent off-by-one regressions.💡 Proposed test refinement
func TestHandleWebhookBodySizeLimit(t *testing.T) { t.Run("rejects oversized request body", func(t *testing.T) { @@ - oversizedBody := strings.NewReader(strings.Repeat("x", 26*1024*1024)) + oversizedBody := strings.NewReader(strings.Repeat("x", maxWebhookPayloadSize+1)) req := httptest.NewRequest(http.MethodPost, "/webhook", oversizedBody) req.Header.Set("X-Hub-Signature", "sha1=invalid") w := httptest.NewRecorder() @@ assert.Equal(t, http.StatusRequestEntityTooLarge, w.Code) }) + t.Run("accepts request body at exact limit", func(t *testing.T) { + _, mockAPI, _, _, _ := GetTestSetup(t) + p := NewPlugin() + p.initializeAPI() + p.SetAPI(mockAPI) + p.client = pluginapi.NewClient(mockAPI, p.Driver) + p.setConfiguration(&Configuration{ + WebhookSecret: webhookSecret, + }) + + mockAPI.On("LogInfo", "Webhook event received") + + bodyAtLimit := strings.NewReader(strings.Repeat("x", maxWebhookPayloadSize)) + req := httptest.NewRequest(http.MethodPost, "/webhook", bodyAtLimit) + req.Header.Set("X-Hub-Signature", "sha1=invalid") + w := httptest.NewRecorder() + + p.handleWebhook(w, req) + + assert.Equal(t, http.StatusUnauthorized, w.Code) + }) + t.Run("accepts normal sized request body", func(t *testing.T) { @@ }) }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@server/plugin/webhook_test.go` around lines 33 - 77, The test TestHandleWebhookBodySizeLimit uses a hardcoded 26*1024*1024 size; replace that with maxWebhookPayloadSize+1 to use the production constant and avoid drift, and add an additional subtest that sends a request body of exactly maxWebhookPayloadSize to ensure p.handleWebhook enforces the boundary correctly (oversized -> StatusRequestEntityTooLarge, exactly at limit -> accepted/falls through to signature check which returns StatusUnauthorized in existing tests). Reference TestHandleWebhookBodySizeLimit, p.handleWebhook, and maxWebhookPayloadSize when making the changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@server/plugin/webhook_test.go`:
- Around line 33-77: The test TestHandleWebhookBodySizeLimit uses a hardcoded
26*1024*1024 size; replace that with maxWebhookPayloadSize+1 to use the
production constant and avoid drift, and add an additional subtest that sends a
request body of exactly maxWebhookPayloadSize to ensure p.handleWebhook enforces
the boundary correctly (oversized -> StatusRequestEntityTooLarge, exactly at
limit -> accepted/falls through to signature check which returns
StatusUnauthorized in existing tests). Reference TestHandleWebhookBodySizeLimit,
p.handleWebhook, and maxWebhookPayloadSize when making the changes.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 584138ee-2151-4d7a-bc5a-c9691b5524df
📒 Files selected for processing (2)
server/plugin/webhook.goserver/plugin/webhook_test.go
Summary
Add http.MaxBytesReader to the webhook handler to cap incoming request bodies at 25 MB (matching GitHub's documented maximum webhook payload size). This ensures oversized requests are rejected immediately with HTTP 413 before being read into memory, regardless of any upstream transport-layer protections.
This is a defense-in-depth hardening measure — the Mattermost plugin IPC layer already prevents exploitation, but the code should not rely on that external protection.
Ticket Link
https://mattermost.atlassian.net/browse/MM-68166