From 40feb86ba4657d5cb4ef3077d2a4a38abbd8b395 Mon Sep 17 00:00:00 2001 From: shaw Date: Wed, 29 Apr 2026 22:11:45 +0800 Subject: [PATCH] fix(httputil): add decompression bomb guard and fix errcheck lint --- backend/internal/pkg/httputil/body.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/backend/internal/pkg/httputil/body.go b/backend/internal/pkg/httputil/body.go index 31bba8c5..cee12948 100644 --- a/backend/internal/pkg/httputil/body.go +++ b/backend/internal/pkg/httputil/body.go @@ -16,6 +16,9 @@ import ( const ( requestBodyReadInitCap = 512 requestBodyReadMaxInitCap = 1 << 20 + // maxDecompressedBodySize limits the decompressed request body to 64 MB + // to prevent decompression bomb attacks. + maxDecompressedBodySize = 64 << 20 ) // ReadRequestBodyWithPrealloc reads request body with preallocated buffer based @@ -69,21 +72,21 @@ func decompressRequestBody(encoding string, raw []byte) ([]byte, error) { return nil, err } defer dec.Close() - return io.ReadAll(dec) + return io.ReadAll(io.LimitReader(dec, maxDecompressedBodySize)) case "gzip", "x-gzip": gr, err := gzip.NewReader(bytes.NewReader(raw)) if err != nil { return nil, err } - defer gr.Close() - return io.ReadAll(gr) + defer func() { _ = gr.Close() }() + return io.ReadAll(io.LimitReader(gr, maxDecompressedBodySize)) case "deflate": zr, err := zlib.NewReader(bytes.NewReader(raw)) if err != nil { return nil, err } - defer zr.Close() - return io.ReadAll(zr) + defer func() { _ = zr.Close() }() + return io.ReadAll(io.LimitReader(zr, maxDecompressedBodySize)) default: return nil, errors.New("unsupported Content-Encoding") }