|
| 1 | +From fe423c373907c1eee207964c52e73740ea293f05 Mon Sep 17 00:00:00 2001 |
| 2 | +From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= <essen@ninenines.eu> |
| 3 | +Date: Tue, 12 May 2026 12:12:20 +0200 |
| 4 | +Subject: [PATCH] Reject multipart header blocks above 2048 bytes |
| 5 | + |
| 6 | +This is a soft limit. If the data is already in the buffer, |
| 7 | +the header block will be parsed normally. |
| 8 | + |
| 9 | +A hardcoded value of 2048 was chosen because it is twice |
| 10 | +larger than the largest expected multipart header blocks. |
| 11 | + |
| 12 | +Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> |
| 13 | +Upstream-reference: https://github.com/ninenines/cowboy/commit/5c6a2061b41bb5771c4659fac7d5a822dca5bafb.patch |
| 14 | +--- |
| 15 | + deps/cowboy/src/cowboy_req.erl | 16 ++++++++++++---- |
| 16 | + 1 file changed, 12 insertions(+), 4 deletions(-) |
| 17 | + |
| 18 | +diff --git a/deps/cowboy/src/cowboy_req.erl b/deps/cowboy/src/cowboy_req.erl |
| 19 | +index 3f87677..e910b7f 100644 |
| 20 | +--- a/deps/cowboy/src/cowboy_req.erl |
| 21 | ++++ b/deps/cowboy/src/cowboy_req.erl |
| 22 | +@@ -611,11 +611,9 @@ read_part(Req, Opts) -> |
| 23 | + read_part(Buffer, Opts, Req=#{multipart := {Boundary, _}}) -> |
| 24 | + try cow_multipart:parse_headers(Buffer, Boundary) of |
| 25 | + more -> |
| 26 | +- {Data, Req2} = stream_multipart(Req, Opts, headers), |
| 27 | +- read_part(<< Buffer/binary, Data/binary >>, Opts, Req2); |
| 28 | ++ read_part_more(Buffer, Opts, Req); |
| 29 | + {more, Buffer2} -> |
| 30 | +- {Data, Req2} = stream_multipart(Req, Opts, headers), |
| 31 | +- read_part(<< Buffer2/binary, Data/binary >>, Opts, Req2); |
| 32 | ++ read_part_more(Buffer2, Opts, Req); |
| 33 | + {ok, Headers0, Rest} -> |
| 34 | + Headers = maps:from_list(Headers0), |
| 35 | + %% Reject multipart content containing duplicate headers. |
| 36 | +@@ -630,6 +628,16 @@ read_part(Buffer, Opts, Req=#{multipart := {Boundary, _}}) -> |
| 37 | + }, Stacktrace) |
| 38 | + end. |
| 39 | + |
| 40 | ++%% We reject multipart header blocks that are twice the maximum |
| 41 | ++%% size of the largest expected multipart header blocks. |
| 42 | ++read_part_more(Buffer, _, _) when byte_size(Buffer) > 2048 -> |
| 43 | ++ exit({request_error, {multipart, headers}, |
| 44 | ++ 'Malformed body; multipart header block too large.' |
| 45 | ++ }); |
| 46 | ++read_part_more(Buffer, Opts, Req0) -> |
| 47 | ++ {Data, Req} = stream_multipart(Req0, Opts, headers), |
| 48 | ++ read_part(<<Buffer/binary, Data/binary>>, Opts, Req). |
| 49 | ++ |
| 50 | + -spec read_part_body(Req) |
| 51 | + -> {ok, binary(), Req} | {more, binary(), Req} |
| 52 | + when Req::req(). |
| 53 | +-- |
| 54 | +2.45.4 |
| 55 | + |
0 commit comments