]> git.kaiwu.me - haproxy.git/commit
BUG/MEDIUM: http-fetch: reject a negative capture id in capture.{req,res}.hdr
authorWilly Tarreau <w@1wt.eu>
Mon, 27 Jul 2026 08:01:05 +0000 (10:01 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Mon, 27 Jul 2026 13:28:17 +0000 (15:28 +0200)
commitce0b1d26eab9821379c710a00ec36cb4e9c748d1
treee64ffb5b02a2a11b5488e1f80836d852435efe35
parent7be8f7a45a6e2da619ce8418a393e7651a433769
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.
src/http_fetch.c