From: Vsevolod Stakhov Date: Sat, 7 Feb 2026 12:22:22 +0000 (+0000) Subject: [Feature] Add v3 request validation and use safe UCL parser flags X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7730e6e3f92cba985cf1228406feff0a06877b00;p=thirdparty%2Frspamd.git [Feature] Add v3 request validation and use safe UCL parser flags Enforce max 2 parts (metadata + message) in /checkv3 multipart requests, returning HTTP 400 for malformed requests with extra parts. Switch UCL parser to UCL_PARSER_SAFE_FLAGS to disable macros/includes in untrusted metadata input. --- diff --git a/src/libserver/protocol.c b/src/libserver/protocol.c index 560282b41e..42b1158c5d 100644 --- a/src/libserver/protocol.c +++ b/src/libserver/protocol.c @@ -2429,6 +2429,15 @@ rspamd_protocol_handle_v3_request(struct rspamd_task *task, (rspamd_mempool_destruct_t) rspamd_multipart_form_free, form); + /* Enforce single message per request: expect at most 2 parts (metadata + message) */ + gsize nparts = rspamd_multipart_form_nparts(form); + if (nparts > 2) { + g_set_error(&task->err, rspamd_protocol_quark(), 400, + "v3 request must contain at most 2 parts (metadata + message), got %lu", + (unsigned long) nparts); + return FALSE; + } + /* Find metadata part */ const struct rspamd_multipart_entry_c *metadata_part = rspamd_multipart_form_find(form, "metadata", sizeof("metadata") - 1); @@ -2450,7 +2459,7 @@ rspamd_protocol_handle_v3_request(struct rspamd_task *task, "msgpack", sizeof("msgpack") - 1) != -1) { is_msgpack = TRUE; - parser = ucl_parser_new(UCL_PARSER_DEFAULT | UCL_PARSER_NO_FILEVARS); + parser = ucl_parser_new(UCL_PARSER_SAFE_FLAGS); ucl_parser_add_chunk_full(parser, (const unsigned char *) metadata_part->data, metadata_part->data_len, ucl_parser_get_default_priority(parser), @@ -2458,7 +2467,8 @@ rspamd_protocol_handle_v3_request(struct rspamd_task *task, UCL_PARSE_MSGPACK); } else { - parser = ucl_parser_new(UCL_PARSER_DEFAULT | UCL_PARSER_NO_FILEVARS); + /* Strict mode: disable UCL macros/includes, treat as plain JSON */ + parser = ucl_parser_new(UCL_PARSER_SAFE_FLAGS); ucl_parser_add_chunk(parser, (const unsigned char *) metadata_part->data, metadata_part->data_len); }