BUG/MEDIUM: http-fetch: reject a negative capture id in capture.{req,res}.hdr
The "capture.req.hdr" and "capture.res.hdr" sample fetches use their integer argument directly as an index in the stream's captures array: idx = args->data.sint; if (idx > (fe->nb_req_cap - 1) || smp->strm->req_cap == NULL || smp->strm->req_cap[idx] == NULL) return 0; Only the upper bound is verified, and unlike "req.hdr" and friends, which rely on val_hdr() to enforce the lower bound of the occurrence number, these two keywords are declared with no argument checker at all. A negative identifier is therefore accepted at boot, and at runtime req_cap[-1] is read; if the pointer found there is not NULL it is then passed to strlen() and returned as a string. This is trivially reproduced with a frontend containing: capture request header Host len 32 http-request return status 200 hdr X-Cap "%[capture.req.hdr(-1)]" which segfaults the worker on the very first request. Since a negative capture identifier is meaningless, the cleanest fix is to reject it at configuration parsing time, as is done for the header occurrence. Let's add a val_cap_id() checker and reference it from both keywords. Note that the "capture-req"/"capture-res" converters in http_conv.c index the same array with an unchecked value too, but they are saved by the list walk that precedes the access and which stops on a NULL <hdr>, so they only fail to capture. They are left untouched. This bug has been there since the keywords were introduced, so this should be backported to all supported versions.
W
Willy Tarreau committed
ce0b1d26eab9821379c710a00ec36cb4e9c748d1
Parent: 7be8f7a
Committed by Christopher Faulet <cfaulet@haproxy.com>
on 7/27/2026, 1:28:17 PM