From: Dmitry Volyntsev Date: Fri, 30 Oct 2026 02:10:44 +0000 (-0700) Subject: WebCrypto: fix crypto.getRandomValues() with non-buffer arguments X-Git-Url: https://git.kaiwu.me/?a=commitdiff_plain;h=76b231ac95dca479c7b4312ccfc0167f3609e526;p=njs.git WebCrypto: fix crypto.getRandomValues() with non-buffer arguments Previously, crypto.getRandomValues() obtained the destination bytes with njs_vm_value_to_bytes(), which also accepts strings and does not make a private copy of shared data. As a result: - for a string argument the random bytes were written into the string data, which may be shared with other strings, including literals in the script; - for r.requestBuffer in nginx the request body seen by subsequent reads was modified. Now, only typed arrays and DataView objects are accepted, and the buffer is made writable before the write. The issue was introduced in 7b2b7612 (0.7.0). --- diff --git a/external/njs_webcrypto_module.c b/external/njs_webcrypto_module.c index c93a2298..c14d9288 100644 --- a/external/njs_webcrypto_module.c +++ b/external/njs_webcrypto_module.c @@ -5555,7 +5555,7 @@ njs_ext_get_random_values(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, buffer = njs_arg(args, nargs, 1); - ret = njs_vm_value_to_bytes(vm, &fill, buffer); + ret = njs_value_buffer_get(vm, buffer, &fill); if (njs_slow_path(ret != NJS_OK)) { return NJS_ERROR; } diff --git a/src/test/njs_unit_test.c b/src/test/njs_unit_test.c index c4671b6b..f133be0b 100644 --- a/src/test/njs_unit_test.c +++ b/src/test/njs_unit_test.c @@ -22049,6 +22049,19 @@ static njs_unit_test_t njs_externals_test[] = "[b[0], $r.buffer[0]]"), njs_str("64,208") }, +#if (NJS_HAVE_OPENSSL) + { njs_str("var b = $r.buffer; crypto.getRandomValues(b);" + "[b.length, $r.buffer[0]]"), + njs_str("22,208") }, + + { njs_str("var v = new DataView(new ArrayBuffer(4));" + "crypto.getRandomValues(v) === v"), + njs_str("true") }, + + { njs_str("var s = 'abc' + 'defgh'; crypto.getRandomValues(s)"), + njs_str("TypeError: first argument must be a Buffer or DataView") }, +#endif + { njs_str("$r.buffer instanceof Buffer"), njs_str("true") },