Skip to content

fix(node:crypto): align scrypt error code with Node.js#6745

Open
JosephDoUrden wants to merge 2 commits into
cloudflare:mainfrom
JosephDoUrden:fix/issue-6639-scrypt-error-codes
Open

fix(node:crypto): align scrypt error code with Node.js#6745
JosephDoUrden wants to merge 2 commits into
cloudflare:mainfrom
JosephDoUrden:fix/issue-6639-scrypt-error-codes

Conversation

@JosephDoUrden
Copy link
Copy Markdown
Contributor

Fixes #6639. The native scrypt path threw a generic Error('Scrypt failed'), so node:crypto.scrypt(...) and scryptSync(...) came back without the code: 'ERR_CRYPTO_INVALID_SCRYPT_PARAMS' Node.js sets for invalid params. Wrapped the native call so the failure surfaces as a RangeError with that code and the Invalid scrypt params message.

Second part of the issue: BoringSSL's EVP_PBE_scrypt does not enforce 128 * r * (N + p + 2) <= maxmem the way OpenSSL does, so cases like {N:32768, r:8, p:1, maxmem:0} (coalesced to the 32 MiB default) succeeded in workerd while throwing on Node. Added the missing memory check on the JS side, run alongside the native call so the error path matches Node's async (callback) and sync (throw) shapes. Uses BigInt because the operands can each be up to 2**32 - 1, and their product would overflow a JS Number's safe integer range.

Tests: crypto_scrypt-test now asserts err.code on the existing bad and toobig vectors, plus a regression case {N:32768, p:1, r:8, maxmem:0} straight from the issue. Verified locally with bazel test //src/workerd/api/node/tests/... (355 pass) and bazel test //src/node:node@eslint.

The native scrypt path threw a generic Error('Scrypt failed') so
node:crypto.scrypt(...) and scryptSync(...) returned an error without the
code: 'ERR_CRYPTO_INVALID_SCRYPT_PARAMS' Node.js sets for invalid params.
Wrap the native call so the failure surfaces as a RangeError with that
code and the 'Invalid scrypt params' message.

BoringSSL's EVP_PBE_scrypt also does not enforce
128 * r * (N + p + 2) <= maxmem the way OpenSSL does, so cases like
{N:32768, r:8, p:1, maxmem:0} (coalesced to the 32 MiB default) succeeded
in workerd while throwing on Node. Add the missing memory check on the
JS side, run alongside the native call so the error path matches Node's
async (callback) and sync (throw) shapes. Uses BigInt because the
operands can each be up to 2**32 - 1, and their product would overflow
a JS Number's safe integer range.

Tests now assert err.code on bad and toobig vectors, and a regression
case mirroring the original issue is added to toobig.

Fixes cloudflare#6639
@JosephDoUrden JosephDoUrden requested review from a team as code owners May 9, 2026 12:23
Comment thread src/node/internal/crypto_scrypt.ts Outdated
Comment thread src/node/internal/crypto_scrypt.ts
Address review feedback: the previous catch threw a fresh
ERR_CRYPTO_INVALID_SCRYPT_PARAMS for anything, which discarded the
already-coded error from checkScryptMemory and would have masked
unrelated failures from the native call.

normaliseScryptError now only rewrites the exact generic Error
('Scrypt failed', no .code) that the workerd C++ scrypt path emits.
Anything that already carries a .code (such as the
ERR_CRYPTO_INVALID_SCRYPT_PARAMS thrown by the JS-side memory check)
or anything with a different message passes through unchanged.
@JosephDoUrden JosephDoUrden requested a review from jasnell May 9, 2026 14:29
@JosephDoUrden
Copy link
Copy Markdown
Contributor Author

The native getScrypt throws a plain Error('Scrypt failed') with no .code, so a plain rej(err) would leave the bad/toobig cases without the code the issue is asking for. normaliseScryptError only rewraps that exact shape, anything already coded (like checkScryptMemory's throw) or with a different message goes through unchanged. @jasnell

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cloudflare Workers node:crypto scrypt: Missing Error Codes and maxmem=0 Mismatch

2 participants