]> git.kaiwu.me - njs.git/commitdiff
Webcrypto: fix buffer overflow when exporting large keys to JWK
authorDmitry Volyntsev <xeioex@nginx.com>
Fri, 12 Jun 2026 01:20:01 +0000 (18:20 -0700)
committerDmitry Volyntsev <xeioexception@gmail.com>
Thu, 2 Jul 2026 22:11:19 +0000 (15:11 -0700)
njs_export_base64url_bignum() and qjs_export_base64url_bignum() wrote
BN_num_bytes() bytes into a fixed 512-byte stack buffer without a bound
check.  An RSA key with a modulus larger than 4096 bits (over 512 bytes),
generated or imported via SPKI/PKCS8, overflowed the buffer during
exportKey("jwk").

While here, add exception throwing on a parallel import part in both
engines.

Reported by Vaibhav Rajput.

external/njs_webcrypto_module.c
external/qjs_webcrypto_module.c

index bd464626dcf4d68fdd3e9f6d27dd3ef8a0dbade3..7e2b950aaf9872d6082051ec57eb5de96c853266 100644 (file)
@@ -2166,6 +2166,11 @@ njs_export_base64url_bignum(njs_vm_t *vm, njs_opaque_value_t *retval,
         size = BN_num_bytes(v);
     }
 
+    if (njs_slow_path(size > sizeof(buf))) {
+        njs_vm_range_error(vm, "JWK key too long: %uz > 512", size);
+        return NJS_ERROR;
+    }
+
     if (njs_bn_bn2binpad(v, &buf[0], size) <= 0) {
         return NJS_ERROR;
     }
@@ -3177,6 +3182,7 @@ njs_import_base64url_bignum(njs_vm_t *vm, njs_opaque_value_t *value)
     (void) njs_decode_base64url_length(&data, &decoded.length);
 
     if (njs_slow_path(decoded.length > sizeof(buf))) {
+        njs_vm_range_error(vm, "JWK key too long: %uz > 512", decoded.length);
         return NULL;
     }
 
index 42ca79757adf0b3fb983e73d19d8d14f1a124b79..36d0d75f8905f90e0e555bb067947b1800ec09ff 100644 (file)
@@ -1405,6 +1405,11 @@ qjs_export_base64url_bignum(JSContext *cx, const BIGNUM *v, size_t size)
         size = BN_num_bytes(v);
     }
 
+    if (size > sizeof(buf)) {
+        JS_ThrowRangeError(cx, "JWK key too long: %zu > 512", size);
+        return JS_EXCEPTION;
+    }
+
     if (njs_bn_bn2binpad(v, &buf[0], size) <= 0) {
         JS_ThrowInternalError(cx, "njs_bn_bn2binpad() failed");
         return JS_EXCEPTION;
@@ -3076,6 +3081,7 @@ qjs_import_base64url_bignum(JSContext *cx, JSValue value)
 
     if (decoded.length > sizeof(buf)) {
         JS_ThrowRangeError(cx, "JWK key too long: %zu > 512", decoded.length);
+        JS_FreeCString(cx, (char *) data.start);
         return NULL;
     }