Skip to content

Commit 9a43c16

Browse files
[AutoPR- Security] Patch nginx for CVE-2026-8711 [HIGH] (microsoft#17432)
Co-authored-by: akhila-guruju <v-guakhila@microsoft.com>
1 parent 53497ef commit 9a43c16

2 files changed

Lines changed: 126 additions & 5 deletions

File tree

SPECS/nginx/CVE-2026-8711.patch

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
From 2bf4601a94c2a22b715d74e6d92dedb1850d56d3 Mon Sep 17 00:00:00 2001
2+
From: Dmitry Volyntsev <xeioex@nginx.com>
3+
Date: Tue, 12 May 2026 16:52:56 -0700
4+
Subject: [PATCH] Fetch: fixed heap buffer overflow in proxy URL credentials.
5+
6+
The destination buffers for the decoded user and password in
7+
ngx_js_parse_proxy_url() were a fixed 128 bytes, while the encoded
8+
input length was bounded only by the URL length. Since
9+
ngx_unescape_uri() writes at most one byte per input byte, raw
10+
credentials longer than 128 bytes overflowed the buffer; the
11+
length check ran only after the decode.
12+
13+
The fix is to size the destination buffer based on the encoded
14+
input length.
15+
16+
The bug appeared in dea8318 (0.9.4).
17+
18+
Upstream patch reference: https://github.com/nginx/njs/commit/2bf4601a94c2a22b715d74e6d92dedb1850d56d3.patch
19+
---
20+
nginx/ngx_js.c | 18 ++++++++----------
21+
nginx/t/js_fetch_proxy_variable.t | 11 ++++++++++-
22+
2 files changed, 18 insertions(+), 11 deletions(-)
23+
24+
diff --git a/nginx/ngx_js.c b/nginx/ngx_js.c
25+
index da50d766a..f3ca74d85 100644
26+
--- a/nginx/ngx_js.c
27+
+++ b/nginx/ngx_js.c
28+
@@ -3549,12 +3549,12 @@ ngx_js_parse_proxy_url(ngx_pool_t *pool, ngx_log_t *log, ngx_str_t *url,
29+
pass_start = colon + 1;
30+
pass_len = at - pass_start;
31+
32+
- decoded_user = ngx_pnalloc(pool, 128);
33+
+ decoded_user = ngx_pnalloc(pool, user_len);
34+
if (decoded_user == NULL) {
35+
return NGX_ERROR;
36+
}
37+
38+
- decoded_pass = ngx_pnalloc(pool, 128);
39+
+ decoded_pass = ngx_pnalloc(pool, pass_len);
40+
if (decoded_pass == NULL) {
41+
return NGX_ERROR;
42+
}
43+
@@ -3562,24 +3562,22 @@ ngx_js_parse_proxy_url(ngx_pool_t *pool, ngx_log_t *log, ngx_str_t *url,
44+
p = user_start;
45+
decoded_end = decoded_user;
46+
ngx_unescape_uri(&decoded_end, &p, user_len, NGX_UNESCAPE_URI);
47+
-
48+
user_len = decoded_end - decoded_user;
49+
- if (user_len == 0 || user_len > 127) {
50+
+
51+
+ if (user_len == 0) {
52+
ngx_log_error(NGX_LOG_ERR, log, 0,
53+
- "js_fetch_proxy username invalid or too long "
54+
- "(max 127 bytes after decoding)");
55+
+ "js_fetch_proxy username is empty");
56+
return NGX_ERROR;
57+
}
58+
59+
p = pass_start;
60+
decoded_end = decoded_pass;
61+
ngx_unescape_uri(&decoded_end, &p, pass_len, NGX_UNESCAPE_URI);
62+
-
63+
pass_len = decoded_end - decoded_pass;
64+
- if (pass_len == 0 || pass_len > 127) {
65+
+
66+
+ if (pass_len == 0) {
67+
ngx_log_error(NGX_LOG_ERR, log, 0,
68+
- "js_fetch_proxy password invalid or too long "
69+
- "(max 127 bytes after decoding)");
70+
+ "js_fetch_proxy password is empty");
71+
return NGX_ERROR;
72+
}
73+
74+
diff --git a/nginx/t/js_fetch_proxy_variable.t b/nginx/t/js_fetch_proxy_variable.t
75+
index 7399d28f6..b1fcbadda 100644
76+
--- a/nginx/t/js_fetch_proxy_variable.t
77+
+++ b/nginx/t/js_fetch_proxy_variable.t
78+
@@ -59,6 +59,12 @@ http {
79+
js_fetch_proxy $proxy_url;
80+
js_content test.http_fetch;
81+
}
82+
+
83+
+ location /dynamic_user_proxy {
84+
+ set $proxy_url "http://$arg_user:p@127.0.0.1:%%PORT_8081%%";
85+
+ js_fetch_proxy $proxy_url;
86+
+ js_content test.http_fetch;
87+
+ }
88+
}
89+
90+
server {
91+
@@ -128,7 +134,7 @@ $t->write_file('test.js', <<EOF);
92+
93+
EOF
94+
95+
-$t->try_run('no js_fetch_proxy')->plan(3);
96+
+$t->try_run('no js_fetch_proxy')->plan(4);
97+
98+
###############################################################################
99+
100+
@@ -138,5 +144,8 @@ like(http_get('/dynamic_proxy'), qr/PROXY:Basic\s+dGVzdHVzZXI6dGVzdHBhc3M=/,
101+
'dynamic proxy URL with auth');
102+
like(http_get('/dynamic_empty_proxy'), qr/ORIGIN:OK/,
103+
'dynamic empty proxy URL bypasses proxy');
104+
+like(http_get('/dynamic_user_proxy?user=' . ('a' x 200)),
105+
+ qr/PROXY:BAD-AUTH/,
106+
+ 'long user in dynamic proxy URL decoded without overflow');
107+
108+
###############################################################################

SPECS/nginx/nginx.spec

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Name: nginx
66
# Currently on "stable" version of nginx from https://nginx.org/en/download.html.
77
# Note: Stable versions are even (1.20), mainline versions are odd (1.21)
88
Version: 1.28.3
9-
Release: 2%{?dist}
9+
Release: 3%{?dist}
1010
License: BSD-2-Clause
1111
Vendor: Microsoft Corporation
1212
Distribution: Azure Linux
@@ -30,6 +30,10 @@ Patch7: CVE-2026-40701.patch
3030
Patch8: CVE-2026-42934.patch
3131
Patch9: CVE-2026-42945.patch
3232
Patch10: CVE-2026-42946.patch
33+
34+
# njs patches start at 1001 to keep them separate from nginx patches
35+
Patch1001: CVE-2026-8711.patch
36+
3337
BuildRequires: libxml2-devel
3438
BuildRequires: libxslt-devel
3539
BuildRequires: openssl-devel
@@ -73,10 +77,16 @@ Requires: opentelemetry-cpp
7377
The OpenTelemetry module for Nginx
7478

7579
%prep
76-
%autosetup -p1
77-
pushd ../
78-
mkdir -p nginx-njs
79-
tar -C nginx-njs -xf %{SOURCE2}
80+
%autosetup -N
81+
%autopatch -p1 -M 1000
82+
83+
mkdir -p ../nginx-njs
84+
tar -C ../nginx-njs -xf %{SOURCE2}
85+
86+
pushd ../nginx-njs/njs-%{njs_version}
87+
%autopatch -p1 -m 1001
88+
popd
89+
8090

8191
%build
8292
sh configure \
@@ -172,6 +182,9 @@ rm -rf nginx-tests
172182
%dir %{_sysconfdir}/%{name}
173183

174184
%changelog
185+
* Mon May 25 2026 Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> - 1.28.3-3
186+
- Patch for CVE-2026-8711
187+
175188
* Fri May 15 2026 Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> - 1.28.3-2
176189
- Patch for CVE-2026-42946, CVE-2026-42945, CVE-2026-42934, CVE-2026-40701, CVE-2026-40460
177190

0 commit comments

Comments
 (0)