Commit graph

8663 commits

Author SHA1 Message Date
Vadim Zhestikov
dbfd4b52ab Version bump 2026-07-16 12:27:25 -07:00
Roman Arutyunyan
073ab5db06 nginx-1.31.3-RELEASE
Some checks failed
buildbot / buildbot (push) Has been cancelled
2026-07-15 20:03:14 +04:00
Roman Arutyunyan
700dc9e0e7 Avoid duplicate subrequest finalization
Previously, if a subrequest was posted twice, it could be finalized in
both calls, excessively reducing r->main->count and potentially leading
to a use-after-free.

The fix is to avoid posting a request if it's already posted.  Also,
as a hardening measure, r->write_event_handler is now reset to a no-op
handler during active subrequest finalization.

The problem manifests itself in ngx_http_ssi_filter_module during
unbuffered proxying.  If a subrequest is created for an SSI include
statement while the main request has some data postponed by another
include, this subrequest becomes double-posted when the main request
data is flushed.  The first post comes from ngx_http_subrequest() and
the second one comes from ngx_http_postpone_filter().  In case of a
quick subrequest finalization, the above mentioned problem happens.

Reported by P4P3R-HAK.
2026-07-15 19:51:22 +04:00
Pavel Pautov
0cca8e055a Fixed uninitialized memory read caused by stale regex captures.
When ngx_http_regex_exec() reallocates r->captures array, it doesn't update
r->ncaptures value, if regex didn't match. So the next use of unnamed regex
capture triggers uninitialized read and potential buffer overrun.

This config demonstrates the issue:
    map test $my_map {
        volatile;

        ~mismatch(.*) 1; # reallocates r->captures in subrequests

        default "";
    }

    server {
        location ~(.*) { # sets r->ncaptures
            slice 50;

            # $1 will read from uninitialized memory in slice subrequests
            proxy_set_header Test $my_map$1;

            proxy_set_header Range $slice_range;
            proxy_pass http://backend;
        }
    }

The issue was introduced by 746fba0d79.
2026-07-15 19:51:22 +04:00
Roman Arutyunyan
a8289aa69c Script: avoid garbage at the end of the result string
If the script result turned out to be shorter than its predicted
length, the result string contained uninitialized bytes at the end.
The fix is to cut the result string by its actual size.

The following locations returned trailing garbage to the client with
URI "/1234abcd".

    map $uri $foo {
        ~^/(?<bar>[0-9]).*$ $bar;
    }

    location ~(?<bar>[0-9]*)[a-z]*$ {
        return 200 $1:$foo;
    }

    location ~(?<bar>[0-9]*)[a-z]*$ {
        set $qux $1:$foo;
        return 200 $qux;
    }
2026-07-15 19:51:22 +04:00
Maxim Dounin
25f920eca9 Script: buffer overrun protection in direct script usage.
Following the previous change, this change adds script overrun
protection to direct script evaluation in the proxy, fastcgi, scgi,
uwsgi, grpc proxy, index, and try_files modules.

This change is a modified version of a patch by Maxim Dounin.  The
modifications include ngx_http_proxy_v2_module and hardened size checks.

Signed-off-by: Roman Arutyunyan <arut@nginx.com>
Origin: <https://freenginx.org/hg/nginx/rev/7e4d7feb4c77>
2026-07-15 19:51:22 +04:00
Maxim Dounin
4d32a2703c Access log: buffer overrun protection.
Similarly to generic script operations, access log script copy operations
now check if there is enough room in the buffer.

Signed-off-by: Roman Arutyunyan <arut@nginx.com>
Origin: <https://freenginx.org/hg/nginx/rev/ceff7ca7785a>
2026-07-15 19:51:22 +04:00
Maxim Dounin
b767540492 Script: buffer overrun protection.
With this change, all script copy operations now check if there is
enough room in the buffer.  To do so, the script engine now provides the
e->end pointer, which specifies expected buffer end, and each copy
operation is checked against it with the ngx_http_script_check_length()
function.

The e->end pointer is optional and only checked when set, thus
introducing no incompatible API changes.  All standard functions were
updated to use it, notably ngx_http_complex_value(), ngx_http_script_run(),
ngx_http_script_regex_start_code(), ngx_http_script_complex_value_code().
Direct script evaluation in the proxy, fastcgi, scgi, uwsgi, grpc proxy,
index, and try_files modules will be updated by a separate patch.

In particular, this catches issues as observed when evaluating variables
with side effects, such as in the following configuration:

    map $uri $map {
        ~(?<capture>.*) $capture;
    }

    set $capture "";
    set $temp "$capture $map";

As well as when evaluating non-cacheable variables, where length of a
variable might change between length and copy codes, such as in the
following configuration:

    map prefix:$capture $map_volatile {
        volatile;
        ~(?<capture>.*) $capture;
    }

    set $capture "";
    set $temp "$map_volatile";

Similar changes were made in the stream module.

Signed-off-by: Roman Arutyunyan <arut@nginx.com>
Origin: <https://freenginx.org/hg/nginx/rev/d172f506ab5f>
2026-07-15 19:51:22 +04:00
Maxim Dounin
28219209e0 Script: simplified copy capture codes.
Signed-off-by: Roman Arutyunyan <arut@nginx.com>
Origin: <https://freenginx.org/hg/nginx/rev/0fd5e6155817>
2026-07-15 19:51:22 +04:00
Roman Arutyunyan
d798231b56 Disable HTTP keepalive for HTTP CONNECT requests
As per RFC 2817 Section 5.2:

Like any other pipelined HTTP/1.1 request, data to be tunneled may be
sent immediately after the blank line. The usual caveats also apply:
data may be discarded if the eventual response is negative, and the
connection may be reset with no response if more than one TCP segment
is outstanding.
2026-07-15 18:37:17 +04:00
Roman Arutyunyan
f475868196 Reject HTTP CONNECT requests with body
As per RFC 9110, Section 9.3.6:

A CONNECT request message does not have content.

Also, as per Section 8.6:

A user agent SHOULD NOT send a Content-Length header field when the
request message does not contain content and the method semantics do
not anticipate such data.
2026-07-15 18:37:17 +04:00
Roman Arutyunyan
f847651efa Tunnel: ignore request body
Previously, client request body was considered tunnel payload.

Reported by NiubiKlasLi.
2026-07-15 18:37:17 +04:00
Patrik Wall
6ab37e105c Stream: proxy_socket_sndbuf and proxy_socket_rcvbuf directives
Some checks are pending
buildbot / buildbot (push) Waiting to run
Similarly to "listen ... sndbuf/rcvbuf", proxy_socket_sndbuf and
proxy_socket_rcvbuf can be used to set the SO_SNDBUF and SO_RCVBUF
socket options, respectively, on upstream connections.  By default,
the values are left unchanged.

Closes: https://github.com/nginx/nginx/issues/1297
2026-07-15 16:59:06 +04:00
Patrik Wall
04d118301f Upstream: proxy_socket_sndbuf and proxy_socket_rcvbuf directives
Similarly to "listen ... sndbuf/rcvbuf", proxy_socket_sndbuf and
proxy_socket_rcvbuf can be used to set the SO_SNDBUF and SO_RCVBUF
socket options, respectively, for upstream connections.  By default,
the values are left unchanged.

Similar changes made in fastcgi, grpc, scgi, uwsgi, tunnel.
2026-07-15 16:59:06 +04:00
Patrik Wall
3fe9fc4573 Events: support for SO_SNDBUF on outbound peer connections
ngx_event_connect_peer() honors SO_RCVBUF via pc->rcvbuf but had
no equivalent for SO_SNDBUF.  This adds pc->sndbuf and the matching
setsockopt() call, mirroring the existing SO_RCVBUF path.
Both setsockopt() calls are made non-fatal.

Existing callers leaving sndbuf at 0 retain prior behavior, since
setsockopt() is only invoked when the field is non-zero.  These
fields are consumed by various proxying modules in follow-up commits.
2026-07-15 16:59:06 +04:00
Sergey Kandaurov
a277069b14 HTTP/2: reject requests with out-of-order pseudo-headers
Handling of pseudo-headers is refactored to be more in line with
HTTP/3 implementation, that is, a request line is now constructed
as soon as pseudo-headers are followed by regular fields.  Here
this plugs a missing handling for absent mandatory or out-of-order
pseudo-headers.

Such requests are now rejected immediately as malformed.

Closes: https://github.com/nginx/nginx/issues/1526
2026-07-15 16:58:20 +04:00
Aleksei Bavshin
a28f950fe4 Configure: include crypt.h for crypt() feature tests 2026-07-15 15:02:04 +04:00
Maxim Dounin
cf94d5691a Perl: request object validation
Previously, using stale request objects resulted in accesses to already
freed memory, causing segmentation faults:

    location /stale {
        perl 'sub {
            my $r = shift;
            $prev->log_error(0, "next request arrived") if $prev;
            $prev = $r;
            $r->send_http_header;
            return OK;
        }';
    }

Similarly, incorrectly blessed objects might cause segmentation faults,
such as in the following configuration:

    location /bless {
        perl 'sub {
            my $v = 10;
            my $r = bless \$v, "nginx";
            $r->send_http_header;
            return OK;
        }';
    }

With this change, active request object is recorded in the
ngx_http_perl_call_handler() function, and checked by
ngx_http_perl_set_request() to prevent use of unexpected request
objects.

Reported by Axel Mierczuk, Keith Hoodlet, 1Password’s Off-by-1 Labs.

Signed-off-by: Sergey Kandaurov <pluknet@nginx.com>
Origin: https://freenginx.org/hg/nginx/rev/86a2685756ae
2026-07-15 14:06:50 +04:00
Maxim Dounin
d9b7669666 Perl: introduced reference counting for perl scalars
Perl scalars might have a limited lifetime, and using them without
appropriate reference counting is incorrect.  In particular, heap
use-after-free was observed in the following configuration (note the
"eval", which limits lifetime of the string being printed), which
demonstrates that the previously used SvREADONLY() optimizations are
incorrect:

    location / {
        perl 'sub {
            my $r = shift;
            $r->send_http_header;
            eval q!$r->print("it works")!;
            return OK;
        }';
    }

Similarly, errors were observed with handlers in $r->sleep() and
$r->has_request_body() when a handler comes from an eval, such as in
the following configuration:

    location / {
        perl 'sub {
            my $r = shift;
            $r->sleep(100, eval q!sub {
                my $r = shift;
                $r->send_http_header;
                $r->print("it works");
                return OK;
            }!);
            return OK;
        }';
    }

Accordingly, the SvREADONLY() optimization was removed in
ngx_http_perl_sv2str(), since it is expected to be used for small
strings, and using proper reference counting likely will be more costly
than just copying the string.  In $r->print(), $r->sleep(), and
$r->has_request_body() proper reference counting was implemented, with
decrement operations being performed by pool cleanup handlers.

As a positive side effect, $r->print() can now avoid copying any single
scalar, not just read-only scalars.

Reported by Evan Hellman,
https://github.com/freenginx/nginx/issues/26

Signed-off-by: Sergey Kandaurov <pluknet@nginx.com>
Origin: https://freenginx.org/hg/nginx/rev/7a3dbb7905ad
2026-07-15 14:06:50 +04:00
Maxim Dounin
a6a942fd6a Perl: added handler type checks
Previously, calling $r->sleep() and $r->has_request_body() with an
invalid handler argument, such as a string, resulted in a segmentation
fault.

Signed-off-by: Sergey Kandaurov <pluknet@nginx.com>
Origin: https://freenginx.org/hg/nginx/rev/2442b26850b1
2026-07-15 14:06:50 +04:00
Zhidao HONG
9e32c636c7 Proxy: fixed HTTP/2 upstream with revalidated cache send
Some checks are pending
buildbot / buildbot (push) Waiting to run
Previously, a revalidated cached response could fail on a cached
keepalive connection with "upstream sent frame for unknown stream"
error followed by "cache file contains invalid header".

This happened because after a 304 response, nginx parsed the cached
response while the upstream peer connection was still attached to the
request.  The HTTP/2 proxy code treated cached frames as frames from
that live connection, and could assign a real stream id instead of
treating the cached response as having no real stream.

The fix is to treat cached response parsing as cache-only regardless
of the current upstream peer connection: set the stream id to 0 and
skip live upstream control-frame handling while r->cached is set.

Closes: https://github.com/nginx/nginx/issues/1318
2026-07-14 20:38:57 +08:00
Zhidao HONG
44c66e92c8 Upstream: limit response header field sizes for HTTP/2 and gRPC
HTTP/2 and gRPC upstream response header parsing used the HPACK string
length to allocate header name and value buffers.  The length was not
checked against the configured upstream buffer size before allocation.
A malicious upstream could force nginx to allocate excessive
request-pool memory before the header was rejected.

Reject oversized HTTP/2 header name and value lengths before allocation.
Also keep a per-header-block limit based on the upstream buffer size, so
a header block cannot consume unbounded memory across fields.
2026-07-14 20:38:57 +08:00
Zhidao HONG
5f92d7afb8 HTTP/2: fixed INITIAL_WINDOW_SIZE with saved state
The window size change was previously kept in a local variable while
processing SETTINGS parameters.  If parsing was suspended after
SETTINGS_INITIAL_WINDOW_SIZE, the value was lost on resume and was
acknowledged without being applied.

Store the initial window size change in the HTTP/2 state until the
SETTINGS frame is fully processed.
2026-07-14 20:38:57 +08:00
David Carlier
db9ba42db8 SSL: fixed memory leak in ngx_ssl_get_ech_outer_server_name().
Some checks are pending
buildbot / buildbot (push) Waiting to run
SSL_ech_get1_status() allocates inner_sni and outer_sni and transfers
ownership to the caller.  On the allocation-failure path the function
returned without freeing them, unlike ngx_ssl_get_ech_status() which
frees both on all paths.
2026-07-13 11:46:20 -07:00
Maxim Dounin
4d0e620f9a Xslt: xml_external_entities directive
Loading of external entities defined in the internal DTD subset,
that is, in the XML document itself, is now disabled by default, and
can be re-enabled with "xml_external_entities on;".  This makes
processing of untrusted XML responses with the xslt module slightly
safer (though still not recommended unless you thoughtfully considered
risks).

To prevent loading we intercept entities defined in the internal
subset via the entityDecl callback, and remove system identifiers from
entities.  This ensures that entities cannot be loaded directly, but
still allows using of public entities with appropriate system XML
catalog.

Additionally, since libxml2 before 2.14.0 (Mar 27 2025) accepts
in-document catalogs by default, these are explicitly disabled.

Signed-off-by: Vadim Zhestikov <v.zhestikov@f5.com>
Origin: https://freenginx.org/hg/nginx/rev/94dae9ab1018
2026-07-13 10:49:14 -07:00
Maxim Dounin
017dbad856 Xslt: disabled loading of external entities over the network
Loading of external entities, including ones defined with the
xml_entities directive, happens while parsing the XML response, and
therefore loading over the network can block the entire worker process
for a long time.  Loading of external DTD subset is disabled for the
very same reason since initial version of the module.

Further, loading over the network is anyway not available by default
since libxml2 2.13.0 (Jun 12 2024) and completely removed in libxml2
2.15.0 (Sep 15 2025).

As such, the XML_PARSE_NONET parsing option (available since libxml2
2.6.2 from 2003) is now used to prevent loading of external entities
over the network.

Signed-off-by: Vadim Zhestikov <v.zhestikov@f5.com>
Origin: https://freenginx.org/hg/nginx/rev/081c50f47347
2026-07-13 10:49:14 -07:00
Roman Arutyunyan
18ccebb1a8 Fix setting the IPV6_DONTFRAG socket option
Some checks failed
buildbot / buildbot (push) Has been cancelled
The fix includes the socket option level (IPPROTO_IPV6) in the feature
test and the macro (NGX_HAVE_IPV6_DONTFRAG) in the
ngx_configure_listening_sockets() function.

Reported by Eric Fortis.
2026-07-08 21:23:26 +04:00
vinaykumar-1591
3f720dc784 Upstream: Upgrade header processing
Pass Upgrade through for HTTP/1.x clients only: both for active
connection upgrades (101 Switching Protocols) and for advertising
available upgrades in other responses (RFC 9110 Section 7.8).
Strip it for HTTP/2+ clients where connection-specific headers
are forbidden (RFC 9113 Section 8.2.2, RFC 9114 Section 4.2).
2026-07-08 16:13:45 +04:00
Sergey Kandaurov
29c23ad846 Charset: disabled charset_map with utf-8 in the first column
Some checks failed
buildbot / buildbot (push) Has been cancelled
This undocumented configuration was never expected to work and
resulted in immediate segfaults.

Reported by ret2ddme.
2026-07-03 21:59:53 +04:00
Andrew Clayton
8f3465ac7f GH: explicitly set permissions in workflows
Some checks failed
buildbot / buildbot (push) Has been cancelled
These will override the default repo/org GITHUB_TOKEN scope.
2026-06-30 19:36:43 +01:00
Andrew Clayton
072f6fdbac Revert "HTTP/2: fixed overlapping memcpy in CONTINUATION frames"
Some checks are pending
buildbot / buildbot (push) Waiting to run
This reverts commit 2d71bdcf8b.

This is actually unnecessary. Thanks to Valentin Bartenev for the
analysis

1. ngx_http_v2_handle_continuation() handles split HPACK integers at
   frame boundaries
2. HPACK integers are max 4 bytes (NGX_HTTP_V2_INT_OCTETS)
3. The function is only called when length < 4 (i.e., 1-3 bytes remain)
4. The copy destination is offset by 9 bytes (frame header size)

Since 3 < 9, source and destination never overlap.
2026-06-29 20:22:32 +01:00
Feng Wu
42f8df65b6 Add missing bounds check in ngx_{http,stream}_compile_complex_value()
Some checks failed
buildbot / buildbot (push) Has been cancelled
Complex value compilation scans strings for $1..$9 capture references.
Check that a byte after '$' is present before testing it, matching
ngx_str_t length semantics and avoiding reliance on NUL termination.

Apply the same check to both HTTP and stream implementations.
2026-06-25 09:15:44 -07:00
Feng Wu
2d71bdcf8b HTTP/2: fixed overlapping memcpy in CONTINUATION frames
Some checks are pending
buildbot / buildbot (push) Waiting to run
When processing CONTINUATION frames, ngx_http_v2_handle_continuation()
used ngx_memcpy() to shift header block fragment data past the frame
header.  If the fragment is larger than the frame header (9 bytes),
the source and destination regions overlap, which is undefined
behavior for memcpy.  The same function already uses ngx_memmove()
for another overlapping shift.
2026-06-24 17:57:50 +01:00
Miao Wang
be84ac8bda Configure: set cache line size for loongarch64
Some checks are pending
buildbot / buildbot (push) Waiting to run
Section 8.2 table 54, registers 0x11 - 0x14 (2^6 = 64 bytes)
<https://loongson.github.io/LoongArch-Documentation/Loongson-3A5000-usermanual-EN.html#instruction-set-features-implemented-in-3a5000>

There is no intent to cover 32-bit LoongArch which acceptably falls
through to the default.
2026-06-23 15:24:27 +01:00
Andrew Clayton
e01f4fe3a9 Version bump 2026-06-23 15:22:11 +01:00
Sergey Kandaurov
2fd01ed47a nginx-1.31.2-RELEASE
Some checks failed
buildbot / buildbot (push) Has been cancelled
2026-06-17 07:40:35 -07:00
Sergey Kandaurov
319a0bff15 Charset: fixed another rare buffer overread in recode_from_utf8()
With prerequisites similar to 696a7f1b9, it was possible to gain 1-byte
overread on invalid UTF-8 sequences.  The reason is ngx_utf8_decode()
stops advancing the pointer position on the first encountered invalid
byte.  The fix is to adjust the advanced pointer up to the whole saved
sequence in this case.  Note that this may result in different output
compared to complete invalid UTF-8 sequences, which we can disregard
at this point.

Reported by Han Yan of Xiaomi and p4p3r of CYBERONE.
2026-06-17 07:40:35 -07:00
Roman Arutyunyan
26d824ec3a Upstream: limit header length for HTTP/2 and gRPC
The change applies the HTTP/2 header length limits to avoid buffer
overflow.  See 58a7bc3406 for details.

Reported by Mufeed VH of Winfunc Research.
2026-06-17 07:40:35 -07:00
Roman Arutyunyan
9e293766e7 HTTP/3: avoid recreation of standard client uni streams
Creating a control/encoder/decoder stream while another such stream
already exists, is not allowed.  Also, closing such a stream results
in connection closure with NGX_HTTP_V3_ERR_CLOSED_CRITICAL_STREAM.
However, since stream creation and connection closure are asynchronous,
there could be a window where two control/encoder/decoder streams
could coexist within a single cycle iteration.  This could result
in reusing parsing context, such as encoder insert buffer.

The change adds a mask for all standard client uni streams ever created.
This allows to check if a stream of this type was created before.
While here, mandatory stream validation now also uses this mask.
2026-06-17 07:40:35 -07:00
Roman Arutyunyan
ceccdbd2ee HTTP/3: allocate insert buffer from connection pool
Previously, it was allocated from the encoder stream pool.  This could
lead to use-after-free if the stream was closed and another encoder
stream was opened.

Reported by Trung Nguyen (@everping) of CyStack.
2026-06-17 07:40:35 -07:00
Roman Arutyunyan
875750a4f7 HTTP/3: use max table capacity for insert buffer allocation
Previously, current capacity was used for the allocation, which could
be insufficient if table capacity was later increased.
2026-06-17 07:40:35 -07:00
Sergey Kandaurov
ab976ab39a Updated OpenSSL used for win32 builds
Some checks are pending
buildbot / buildbot (push) Waiting to run
2026-06-16 14:47:04 -07:00
Andrew Clayton
da80db978f GH: fix check-whitespace.yaml error return with multiple commits
Some checks failed
buildbot / buildbot (push) Has been cancelled
Commit 126cb16e3 ("GH: fix check-whitespace.yaml error return with
multiple commits") removed the wrong err=0. Put it back and remove the
*right* one!
2026-06-11 06:23:00 +01:00
Nitin Swami
e09c0d32d5 Access log: fix "request_length" format length
The variable handler uses "%O" format specifier.

Reported by Mufeed VH of Winfunc Research.
2026-06-11 09:12:57 +05:30
Sergey Kandaurov
bedf18f95d Secure link: compare hashes in constant time
Some checks are pending
buildbot / buildbot (push) Waiting to run
Reported by kodareef5
2026-06-11 01:40:19 +05:30
Sergey Kandaurov
b23fdb91ee Secure link: style 2026-06-11 01:40:19 +05:30
Andrew Clayton
126cb16e3d GH: fix check-whitespace.yaml error return with multiple commits
We erroneously reset err to 0 for each commit.
2026-06-10 19:23:40 +01:00
Andrew Clayton
fefae70f63 GH: fix summary formatting for check-whitespace.yaml
Wrap the git log --check output in a markdown code block to prevent
undesirable formatting.
2026-06-10 19:23:40 +01:00
Sergey Kandaurov
8bbaf83d48 Updated link to OpenSSL commit 2026-06-10 22:21:10 +04:00
Sergey Kandaurov
455fbf8c45 Style 2026-06-10 22:21:10 +04:00