From e93db7f99d976f5677e923fb85a0b00ea855f6ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Helleu?= Date: Sat, 6 Jun 2026 09:36:22 +0200 Subject: [PATCH] relay: limit size of partial message received while reading an HTTP request to prevent memory exhaustion A relay client could send data with no end-of-line (an unterminated method or header line) and dribble its payload, making WeeChat accumulate it in the partial message buffer that grew without limit, until all memory was exhausted. This path is reachable before authentication during websocket initialization with the "weechat" and "irc" protocols. The accumulated partial message is now bounded by RELAY_HTTP_PARTIAL_MESSAGE_MAX_LENGTH: once the limit is reached, the extra data is ignored. --- CHANGELOG.md | 1 + src/plugins/relay/relay-http.c | 8 ++++++++ src/plugins/relay/relay-http.h | 9 +++++++++ 3 files changed, 18 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 302c84746..d03faf68e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ - api, relay: fix timing attack on TOTP validation ([GHSA-vhv8-g2r9-cwcc](https://github.com/weechat/weechat/security/advisories/GHSA-vhv8-g2r9-cwcc)) - relay: limit size of decompressed websocket frame with permessage-deflate to prevent memory exhaustion ([GHSA-v2v4-45wm-5cr3](https://github.com/weechat/weechat/security/advisories/GHSA-v2v4-45wm-5cr3)) - relay/weechat: fix empty buffers in client when WeeChat is running on Solaris/illumos +- relay: limit size of partial message received while reading an HTTP request to prevent memory exhaustion - xfer: replace directory separator in remote nick by underscore in download filename to prevent writing the file outside the download directory ([#2321](https://github.com/weechat/weechat/issues/2321)) - xfer: fix out-of-bounds read when receiving empty line in DCC chat ([#2323](https://github.com/weechat/weechat/issues/2323)) - build: fix build on Solaris/illumos (issue #2251) diff --git a/src/plugins/relay/relay-http.c b/src/plugins/relay/relay-http.c index 8c5e74521..1e846df85 100644 --- a/src/plugins/relay/relay-http.c +++ b/src/plugins/relay/relay-http.c @@ -953,6 +953,14 @@ relay_http_recv (struct t_relay_client *client, const char *data) if (client->partial_message) { + /* + * limit the size of the partial message: once the maximum is reached, + * ignore the extra data (protection against a client sending a huge + * amount of data without any end-of-line and dribbling it, which would + * consume all the memory) + */ + if (strlen (client->partial_message) >= RELAY_HTTP_PARTIAL_MESSAGE_MAX_LENGTH) + return; new_partial = realloc (client->partial_message, strlen (client->partial_message) + strlen (data) + 1); diff --git a/src/plugins/relay/relay-http.h b/src/plugins/relay/relay-http.h index f2c8ed6a4..b08d9c973 100644 --- a/src/plugins/relay/relay-http.h +++ b/src/plugins/relay/relay-http.h @@ -60,6 +60,15 @@ enum t_relay_client_http_status */ #define RELAY_HTTP_BODY_MAX_LENGTH (8 * 1024 * 1024) +/* + * maximum length of the partial message accumulated while reading an HTTP + * request: once this limit is reached, the extra data is ignored; this + * protects against a client sending a huge amount of data without any + * end-of-line (an unterminated method or header line), which would consume + * all the memory + */ +#define RELAY_HTTP_PARTIAL_MESSAGE_MAX_LENGTH (8 * 1024 * 1024) + struct t_relay_http_request { enum t_relay_client_http_status status; /* HTTP status */