From 92c9e6bb54731f03bd02281e3616eff4d48fbef2 Mon Sep 17 00:00:00 2001 From: Miki Date: Thu, 4 Dec 2025 02:09:02 -0800 Subject: [PATCH] Add HTTP/3 Host header support for ModSecurity ModSecurity cannot see the Host header in HTTP/3 requests because HTTP/3 uses the `:authority` pseudo-header, which nginx parses into `r->headers_in.server` but doesn't add to the headers list. This commit: - Adds `NGX_HTTP_VERSION_30` case to `http_version` switch - Manually extracts Host from `r->headers_in.server` for HTTP/3 requests - Adds Host header to ModSecurity transaction before processing other headers Fixes #305 false positives from OWASP CRS rule 920280 (Missing Host Header) on HTTP/3 connections. Tested with nginx 1.29.3 and ModSecurity 3.0.13. --- src/ngx_http_modsecurity_rewrite.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/ngx_http_modsecurity_rewrite.c b/src/ngx_http_modsecurity_rewrite.c index ebc4742..4f057d2 100644 --- a/src/ngx_http_modsecurity_rewrite.c +++ b/src/ngx_http_modsecurity_rewrite.c @@ -177,6 +177,11 @@ ngx_http_modsecurity_rewrite_handler(ngx_http_request_t *r) case NGX_HTTP_VERSION_20 : http_version = "2.0"; break; +#endif +#if defined(nginx_version) && nginx_version >= 1025000 + case NGX_HTTP_VERSION_30 : + http_version = "3.0"; + break; #endif default : http_version = ngx_str_to_char(r->http_protocol, r->pool); @@ -212,9 +217,22 @@ ngx_http_modsecurity_rewrite_handler(ngx_http_request_t *r) } /** - * Since incoming request headers are already in place, lets send it to ModSecurity - * + * HTTP/3 uses :authority pseudo-header instead of Host header and nginx + * parses it into r->headers_in.server (see ngx_http_v3_request.c#L982) + * but doesn't add it to the headers list, so ModSecurity never sees it. + * We manually add Host header from r->headers_in.server for ModSecurity + * before processing the remaining headers. */ + if (strcmp(http_version, "3.0") == 0 && r->headers_in.server.len > 0) { + dd("adding Host header from :authority: %.*s", + (int)r->headers_in.server.len, r->headers_in.server.data); + + msc_add_n_request_header(ctx->modsec_transaction, + (const unsigned char *)"Host", 4, + (const unsigned char *)r->headers_in.server.data, + r->headers_in.server.len); + } + ngx_list_part_t *part = &r->headers_in.headers.part; ngx_table_elt_t *data = part->elts; ngx_uint_t i = 0;