Skip to content

Commit cb29b29

Browse files
authored
fix: guard read_body in captcha verify state for HTTP/2 requests (#142)
ngx.req.read_body() raises a runtime error for HTTP/2 (and HTTP/3) requests without a Content-Length header. The captcha verify-state handler in csmod.Allow() called read_body unconditionally, causing nginx to return HTTP 500 whenever a client with an active captcha decision reloaded the challenge page over HTTP/2. The guard mirrors the one already used in get_body(): if the protocol is HTTP/2+ and Content-Length is missing, skip the body read and treat the request as having no POST args. Genuine captcha form submissions are POSTs from browsers that always include Content-Length, so the guard does not interfere with the verification flow. Closes #63
1 parent 6e57e28 commit cb29b29

1 file changed

Lines changed: 12 additions & 2 deletions

File tree

lib/crowdsec.lua

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -761,8 +761,18 @@ function csmod.Allow(ip)
761761
local source, state_id, err = flag.GetFlags(flags)
762762

763763
if previous_uri ~= nil and state_id == flag.VERIFY_STATE then
764-
ngx.req.read_body()
765-
local args, err = ngx.req.get_post_args()
764+
-- HTTP/2 and HTTP/3 requests without Content-Length cause read_body to error.
765+
-- Browsers reloading the captcha page send HTTP/2 GET with no Content-Length,
766+
-- so we skip body-reading in that case and fall through to re-serve the captcha.
767+
-- Genuine captcha form submissions are POSTs with Content-Length set.
768+
local can_read_body = not (ngx.req.http_version() >= 2 and ngx.var.http_content_length == nil)
769+
local args, err
770+
if can_read_body then
771+
ngx.req.read_body()
772+
args, err = ngx.req.get_post_args()
773+
else
774+
args = {}
775+
end
766776

767777
if args and not err then
768778
local captcha_res = args[csmod.GetCaptchaBackendKey()] or 0

0 commit comments

Comments
 (0)