Brief summary
A few invalid arguments to crypto.subtle.deriveBits and crypto.subtle.deriveKey make k6 panic in a background goroutine. The whole process exits, instead of the promise rejecting with an error the script can catch.
- A missing base key (
undefined) crashes deriveBits (ECDH and PBKDF2) and deriveKey (PBKDF2).
- A negative
length crashes ECDH deriveBits.
k6 version
v2.3.0 (latest release). The affected code is unchanged on master as of 2026-09-30 (2a83804).
OS
macOS (darwin/arm64). Not OS-specific.
Docker version and image (if applicable)
No response
Steps to reproduce the problem
Each of these scripts crashes k6:
// missing base key (also crashes with the PBKDF2 algorithm)
export default async function () {
const kp = await crypto.subtle.generateKey({ name: "ECDH", namedCurve: "P-256" }, true, ["deriveBits"]);
await crypto.subtle.deriveBits({ name: "ECDH", public: kp.publicKey }, undefined, 256);
}
// missing base key in deriveKey
export default async function () {
const params = { name: "PBKDF2", hash: "SHA-256", salt: new Uint8Array(16), iterations: 1000 };
await crypto.subtle.deriveKey(params, undefined, { name: "AES-GCM", length: 256 }, true, ["encrypt"]);
}
// negative length
export default async function () {
const kp = await crypto.subtle.generateKey({ name: "ECDH", namedCurve: "P-256" }, true, ["deriveBits"]);
await crypto.subtle.deriveBits({ name: "ECDH", public: kp.publicKey }, kp.privateKey, -8);
}
Wrapping the calls in try/catch doesn't help, as the panic happens in a goroutine.
Expected behaviour
The promise rejects, and the script can handle the error. A missing base key would be a TypeError, as baseKey must be a CryptoKey.
Actual behaviour
k6 exits with a Go panic:
panic: runtime error: invalid memory address or nil pointer dereference
panic: runtime error: slice bounds out of range [:-1]
For reference, PBKDF2 deriveBits with a negative length doesn't crash, but rejects with an error whose name and message are both undefined.
Cause and possible fix
rt.ExportTo(baseKey, &privateKey) leaves privateKey nil for undefined, and nothing checks it before use (subtle_crypto.go#L757 for deriveBits, #L611 for deriveKey). A nil check there, rejecting with a TypeError, would cover all algorithms.
- A negative length passes the
length == 0 and length%8 != 0 checks (#L773-L781), and ECDH then slices with it (elliptic_curve.go#L573). Rejecting length < 0 in DeriveBits would fix it.
Related to #4258, which tracks panics in the WebCrypto module more generally.
Brief summary
A few invalid arguments to
crypto.subtle.deriveBitsandcrypto.subtle.deriveKeymake k6 panic in a background goroutine. The whole process exits, instead of the promise rejecting with an error the script can catch.undefined) crashesderiveBits(ECDH and PBKDF2) andderiveKey(PBKDF2).lengthcrashes ECDHderiveBits.k6 version
v2.3.0 (latest release). The affected code is unchanged on master as of 2026-09-30 (2a83804).
OS
macOS (darwin/arm64). Not OS-specific.
Docker version and image (if applicable)
No response
Steps to reproduce the problem
Each of these scripts crashes k6:
Wrapping the calls in
try/catchdoesn't help, as the panic happens in a goroutine.Expected behaviour
The promise rejects, and the script can handle the error. A missing base key would be a
TypeError, asbaseKeymust be aCryptoKey.Actual behaviour
k6 exits with a Go panic:
For reference, PBKDF2
deriveBitswith a negative length doesn't crash, but rejects with an error whosenameandmessageare bothundefined.Cause and possible fix
rt.ExportTo(baseKey, &privateKey)leavesprivateKeynil forundefined, and nothing checks it before use (subtle_crypto.go#L757 forderiveBits, #L611 forderiveKey). A nil check there, rejecting with aTypeError, would cover all algorithms.length == 0andlength%8 != 0checks (#L773-L781), and ECDH then slices with it (elliptic_curve.go#L573). Rejectinglength < 0inDeriveBitswould fix it.Related to #4258, which tracks panics in the WebCrypto module more generally.