From: Dmitry Volyntsev Date: Fri, 29 May 2026 23:04:56 +0000 (-0700) Subject: Fetch: reject unsafe request targets X-Git-Tag: 1.0.0~33 X-Git-Url: http://git.kaiwu.me/postgresql/log/contrib/postgres_fdw/NGINX-js-1660x332.png%20%22NGINX%20JavaScript%20Banner%22?a=commitdiff_plain;h=50f8b9ae2fa174a81d5674df321461322a2f05a7;p=njs.git Fetch: reject unsafe request targets Reject raw C0 control bytes, space, and DEL in the parsed request target before fetch request serialization. Leave percent-encoded bytes unchanged. --- diff --git a/nginx/ngx_js_fetch.c b/nginx/ngx_js_fetch.c index 10219545..b1bf55ec 100644 --- a/nginx/ngx_js_fetch.c +++ b/nginx/ngx_js_fetch.c @@ -627,6 +627,11 @@ ngx_js_ext_fetch(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, resolve_host = &u.host; } + if (ngx_js_check_request_line_component(u.uri.data, u.uri.len) != NGX_OK) { + njs_vm_error(vm, "invalid url"); + goto fail; + } + ngx_js_fetch_build_request(http, &request, &u.uri, &u, ngx_js_http_proxy(http) && !ngx_js_https(&u)); diff --git a/nginx/ngx_qjs_fetch.c b/nginx/ngx_qjs_fetch.c index 3a41a78c..ec7ac08a 100644 --- a/nginx/ngx_qjs_fetch.c +++ b/nginx/ngx_qjs_fetch.c @@ -364,6 +364,11 @@ ngx_qjs_ext_fetch(JSContext *cx, JSValueConst this_val, int argc, resolve_host = &u.host; } + if (ngx_js_check_request_line_component(u.uri.data, u.uri.len) != NGX_OK) { + JS_ThrowInternalError(cx, "invalid url"); + goto fail; + } + ngx_js_fetch_build_request(http, &request, &u.uri, &u, ngx_js_http_proxy(http) && !ngx_js_https(&u)); diff --git a/nginx/t/js_fetch_objects.t b/nginx/t/js_fetch_objects.t index 1bc0ef93..8bf9cf1d 100644 --- a/nginx/t/js_fetch_objects.t +++ b/nginx/t/js_fetch_objects.t @@ -73,6 +73,10 @@ http { return 200 $http_a; } + location /target { + return 200 $request_uri; + } + location /body { js_content test.body; } @@ -566,6 +570,30 @@ $t->write_file('test.js', < { + const unsafe = [0, 9, 10, 13, 32, 127]; + + for (var i = 0; i < unsafe.length; i++) { + try { + await ngx.fetch('http://127.0.0.1:$p0/a' + + String.fromCharCode(unsafe[i]) + 'b'); + throw new Error('no error'); + + } catch (e) { + if (e.message != 'invalid url') { + throw e; + } + } + } + + return 'OK'; + }, 'OK'], + ['encoded request target', async () => { + var r = await ngx.fetch('http://127.0.0.1:$p0/' + + 'target%0D%0A?q=%00%20'); + var body = await r.text(); + return `\${r.status} \${body}`; + }, '200 /target%0D%0A?q=%00%20'], ]; run(r, tests);