From 76b231ac95dca479c7b4312ccfc0167f3609e526 Mon Sep 17 00:00:00 2001 From: Dmitry Volyntsev Date: Thu, 29 Oct 2026 19:10:44 -0700 Subject: [PATCH] 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). --- external/njs_webcrypto_module.c | 2 +- src/test/njs_unit_test.c | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) 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") }, -- 2.47.3