]> git.kaiwu.me - njs.git/commitdiff
Fetch: fix keepalive with disabled TLS verification
authorDmitry Volyntsev <xeioex@nginx.com>
Thu, 28 May 2026 05:06:55 +0000 (22:06 -0700)
committerDmitry Volyntsev <xeioexception@gmail.com>
Mon, 1 Jun 2026 15:44:59 +0000 (08:44 -0700)
HTTPS connections established with certificate verification disabled are
now excluded from the Fetch keepalive cache.  This prevents a later
verified request to the same destination from reusing a TLS connection
that was created with verification disabled.

nginx/ngx_js_fetch.c
nginx/ngx_qjs_fetch.c
nginx/t/js_fetch_https_keepalive.t

index 608af25ba37c041c5f7576ca9efcbf681484e59f..ac19d704e7a3089f58170cc86efec0e6544e795f 100644 (file)
@@ -584,6 +584,12 @@ ngx_js_ext_fetch(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
 #endif
     }
 
+#if (NGX_SSL)
+    if (http->ssl != NULL && !http->ssl_verify) {
+        http->keepalive = 0;
+    }
+#endif
+
     if (request.method.len == 4
         && ngx_strncasecmp(request.method.data, (u_char *) "HEAD", 4) == 0)
     {
index 066088ce6e5694e20f2cb2922c630166c7dec2f2..6f97e7f3faa7fcd569fa1626b602ba7a5554651b 100644 (file)
@@ -319,6 +319,12 @@ ngx_qjs_ext_fetch(JSContext *cx, JSValueConst this_val, int argc,
 #endif
     }
 
+#if (NGX_SSL)
+    if (http->ssl != NULL && !http->ssl_verify) {
+        http->keepalive = 0;
+    }
+#endif
+
     if (request.method.len == 4
         && ngx_strncasecmp(request.method.data, (u_char *) "HEAD", 4) == 0)
     {
index 86f72d0a08dd420d53624a86c6b6aa2f96696073..36616ca824fa2f4aaee42ce4a2957b377f645419 100644 (file)
@@ -74,6 +74,15 @@ http {
             js_fetch_protocols TLSv1.1 TLSv1.2;
             js_fetch_trusted_certificate myca.crt;
         }
+
+        location /verify_off_no_keepalive {
+            js_content test.verify_off_no_keepalive;
+
+            js_fetch_keepalive 4;
+            js_fetch_ciphers HIGH:!aNull:!MD5;
+            js_fetch_protocols TLSv1.1 TLSv1.2;
+            js_fetch_trusted_certificate myca.crt;
+        }
     }
 
     server {
@@ -174,8 +183,27 @@ $t->write_file('test.js', <<EOF);
         }
     }
 
+    async function verify_off_no_keepalive(r) {
+        try {
+            let resp = await ngx.fetch(`https://ka.example.com:$p1/loc`);
+            let body1 = await resp.text();
+
+            resp = await ngx.fetch(`https://ka.example.com:$p1/loc`,
+                                   { verify: false });
+            let body2 = await resp.text();
+
+            resp = await ngx.fetch(`https://ka.example.com:$p1/loc`);
+            let body3 = await resp.text();
+
+            r.return(200, `\${body1}|\${body2}|\${body3}`);
+
+        } catch (e) {
+            r.return(501, e.message);
+        }
+    }
+
     export default {njs: test_njs, https, sni_isolation,
-                    plain_vs_https_isolation};
+                    plain_vs_https_isolation, verify_off_no_keepalive};
 EOF
 
 my $d = $t->testdir();
@@ -247,7 +275,7 @@ foreach my $name ('1.example.com', 'ka.example.com') {
 
 $t->try_run('no njs.fetch');
 
-$t->plan(5);
+$t->plan(6);
 
 $t->run_daemon(\&dns_daemon, port(8981), $t);
 $t->waitforfile($t->testdir . '/' . port(8981));
@@ -266,6 +294,9 @@ like(http_get('/sni_isolation'),
 like(http_get('/plain_vs_https_isolation'),
        qr/CONN:1\|PLAIN:1\|CONN:2$/s,
        'fetch https->plain->https keepalive isolation');
+like(http_get('/verify_off_no_keepalive'),
+       qr/CONN:1\|CONN:1\|CONN:2$/s,
+       'fetch https verify off is not kept alive');
 
 ###############################################################################