Files
node/test/parallel/test-crypto-random-cache-snapshot.js
Filip Skokan 8c44e38dc6 crypto: reset random caches across snapshots
Startup snapshots retain unused randomInt() and UUID cache entries,
causing deserialized processes to replay the same random values.

Clear the caches after user serialization callbacks and before user
deserialization callbacks. The latter also handles caches refilled by
microtasks, next ticks, or exit handlers after serialization callbacks.

Refs: https://hackerone.com/reports/4059814
Signed-off-by: Filip Skokan <panva.ip@gmail.com>
Assisted-by: Codex
PR-URL: https://github.com/nodejs-private/node-private/pull/987
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Ruy Adorno <ruy@vlt.sh>
CVE-ID: CVE-2026-106074
2026-10-21 12:57:43 +02:00

31 lines
1.0 KiB
JavaScript

'use strict';
const common = require('../common');
if (!common.hasCrypto)
common.skip('missing crypto');
const assert = require('node:assert');
const fixtures = require('../common/fixtures');
const tmpdir = require('../common/tmpdir');
const { buildSnapshot, runWithSnapshot } = require('../common/snapshot');
const entry = fixtures.path('snapshot', 'crypto-random-cache.js');
tmpdir.refresh();
for (const mode of [
'uuid', 'uuidv7', 'object-url', 'async', 'serialize',
'microtask', 'next-tick', 'exit', 'unprimed',
]) {
buildSnapshot(entry, { NODE_TEST_CRYPTO_RANDOM_MODE: mode });
const a = JSON.parse(runWithSnapshot().stdout);
const b = JSON.parse(runWithSnapshot().stdout);
// Values retained by the application at build time are intentionally shared.
assert.deepStrictEqual(a.buildValues, b.buildValues);
for (const phase of ['deserialized', 'main']) {
for (const api of Object.keys(a[phase])) {
assert.notDeepStrictEqual(a[phase][api], b[phase][api], `${mode}: ${phase} ${api}`);
}
}
}