Commit Graph
95 Commits
Author SHA1 Message Date
Chris Tate c82234c639 Refuse TextDecoder and TextEncoder inspection with customInspect: false
With customInspect: false, console.dir's default included, Node skips the
codecs' inspectors and prints their internal slots, which compiled
programs do not model. util.inspect now throws the 'not supported yet'
Error there, where it printed the inspectors' output, and prints
[TextDecoder] and [TextEncoder] past the depth limit as Node does. A
typed codec value applies the option at run time like a checked-dynamic
one.

The customInspect and depth settings an inspection applies return on
every exit: the render runs in a lifted function whose finally restores
them, so an inspection that throws no longer leaves customInspect: false
for the next one.
2026-10-30 08:58:42 -05:00
Malte UblandClaude Opus 5.5 61ab4fbc25 Lower an object spread of a maybe-absent union source
`{ ...maybeRecord }` where the source is `T | undefined` was an SC1090
refusal when the target field had no earlier contributor. Node treats an
absent source as a no-op, so a present source now copies field by field
through the checked extraction (`x!`): the record arm copies the value,
and the absent unit arm throws the catchable TypeError instead of leaving
a required slot unset. An optional target field keeps its no-copy arm.

Corpus 8501 pins the present-source copy and the optional destination; a
new errors-harness case covers both arms of the required-field path.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 09:37:06 -07:00
Chris Tate 27c00f6577 util: runtime format strings, inspect.custom and colors, untyped promisify (#1911) 2026-10-25 17:46:31 -05:00
Chris Tate f0add87f10 Crypto parity: RSA key generation lengths, RSA-PSS keys and encrypted private keys (#2103) 2026-10-25 09:45:21 -05:00
Chris Tate b7915b92a7 Merge main 2026-10-25 06:38:44 -05:00
Chris Tate 0eef6251de Merge main 2026-10-25 02:28:32 -05:00
Chris Tate 6c18c58708 Merge main 2026-10-24 18:21:25 -05:00
Chris Tate 5155793155 Decode passphrases with the key's encoding, and refuse RSA-PSS keys restricted to other digests
createPrivateKey decoded a string passphrase as UTF-8 whatever the
options' encoding, so a correct passphrase given in that encoding failed
to decrypt, and an encrypted export read its passphrase the same way.
Both now decode it with the encoding, as Node does.

An RSA-PSS key whose parameters name a digest the runtime does not sign
with, such as sha512-224 or sha512-256, was imported without its digest,
MGF1 and salt restrictions, so it allowed operations the key forbids. It
now throws a coded SC2020 error that names the digest. Parameters that
are malformed still leave the key unrestricted, as OpenSSL reads them.
2026-10-24 17:33:30 -05:00
Chris Tate 09e50bee50 Merge main 2026-10-24 01:58:41 -05:00
Chris Tate dd4ae4e508 Merge main 2026-10-24 01:57:53 -05:00
Chris Tate 3b951ef4e2 Let objects inherit from JavaScript class prototypes 2026-10-23 23:43:30 -05:00
Chris Tate 37df3c4dfd Support split CommonJS require bindings (#1945) 2026-10-23 19:50:13 -05:00
Chris Tate 5c004a136a Merge main 2026-10-23 19:30:03 -05:00
Chris Tate 072543f5b9 Support X509Certificate fields and methods, TLS certificates and tls.Server contexts 2026-10-23 18:01:19 -05:00
Chris Tate 02597fa3e8 Merge main and give split require cycles the const form's admission 2026-10-23 17:15:33 -05:00
Chris Tate eb8fd9d17b Merge main 2026-10-23 16:02:44 -05:00
Luis Alvarez D 70e6e9b591 Fence split requires that close a CommonJS cycle 2026-10-23 11:40:15 -05:00
Chris Tate 313eb1177c Merge main and fix CI 2026-10-23 09:14:31 -05:00
Chris Tate 19e0fe8bcd Merge main and read cipher options through getters and prototypes 2026-10-23 05:33:14 -05:00
Chris Tate b9275c2693 buffer: fromArrayBuffer ranges, the deprecated constructor, Buffer as a value 2026-10-23 03:05:19 -05:00
Chris Tate f3a903607d Merge main 2026-10-23 00:54:10 -05:00
Chris Tate 7b9ac8d5bb Merge main 2026-10-22 22:26:04 -05:00
Chris Tate 75cf8f0e52 Run zod 4's core constructor factory in the dynamic tier (#1918) 2026-10-22 22:08:46 -05:00
Chris Tate 77c0636826 Include star re-exports in namespace objects, and read causes and instanceof Error like Node under a runtime Error parent
- A module namespace converted to an untyped object, and a computed
  namespace read, use the module's resolved exports, which include the
  members of `export *` declarations.
- `super(message, options)` through a runtime Error parent installs the
  cause as Error does: an inherited `cause` counts, the value is read
  through its getter, and the getter's exception propagates.
- `value instanceof Error` on an instance of a class whose heritage is
  evaluated at run time tests that class's prototype chain for
  Error.prototype. A program with such a class checks prototype chains
  for `instanceof Error` on untyped values.
- The cache of names written on the global object is a Lowerer field
  instead of a WeakMap keyed by the Lowerer.
- errors.test.ts: `"prototype" in Map` answers from the builtin
  constructor's keys now, so it leaves the refused reads and joins a
  check of `in` probes against Node's answers.
2026-10-22 22:00:01 -05:00
Chris Tate 09c132fb2e Merge main 2026-10-22 21:55:35 -05:00
Chris Tate e665913200 Print accessor properties of arrays and fence number keys in defineProperty
- An enumerable getter or setter on an array printed as undefined: the
  property loop rendered the accessor's unused data slot. It now prints
  [Getter], [Setter] or [Getter/Setter], as util.inspect does.
- Object.defineProperty on a live native array with a number key that is
  not an array index (-3, 1.5) skipped the numeric-property fence and
  lost the property on commit. A number key now takes the same fence as
  its string spelling.
2026-10-22 21:39:37 -05:00
Chris Tate 1501559d4a Read and write the "undefined" property for element indexes that are undefined
An element index the checker types as a number can hold undefined at run
time (an element read from a holey array). JavaScript then names the
array's "undefined" property, but the index converted with ToNumber, so
such reads and writes used the "NaN" property: Node prints `10 0,7,0,7`
for a program that sets `values[NaN] = 10` and then writes through two
holes, the compiled program printed `7 0,7,0,7`.

The runtime's noncanonical property table, which holds the properties
named by non-index numbers, now spells one NaN payload
(scr_arr_undefined_key) "undefined". At array element reads, writes,
compound and update writes, destructuring targets and writes in value
position, an index that can be undefined is that key when it is
undefined. The property stays a typed entry of the array, so the Int32[]
contract checks cover it like any element store.

A typed array cannot hold the property: a write through an undefined
index throws the catchable SC1090 error where Node adds it.

Fixes #1640.
2026-10-22 21:34:06 -05:00
Chris Tate dcd86a17da Merge main 2026-10-22 20:52:05 -05:00
Chris Tate 0d016b7554 util: runtime format strings, inspect.custom and colors, untyped promisify 2026-10-22 19:57:46 -05:00
Chris Tate 846552b0e2 Support crypto.getCipherInfo, AES-CCM and the AES key wrap ciphers
getCipherInfo(nameOrNid[, options]) runs in a new runtime unit,
scr_cipher_info.c, over a table that scripts/gen-cipher-info.mjs generates
from Node 24.22's getCipherInfo. The table covers every cipher OpenSSL
names, including the ones without a native implementation. Lookups match
names case-insensitively and accept OpenSSL's nids. The unit applies
cipher.js's argument checks and GetCipherInfo's keyLength and ivLength
rules, and returns the info object in Node's key order. CipherInfo maps
to a checked-dynamic value, so TypeScript and JavaScript code receive
Node's object. Reading the nid Node leaves out for the SIV and SM4 GCM,
CCM and XTS ciphers, where the declared type gives number, throws a
TypeError.

createCipheriv and createDecipheriv support aes-128/192/256-ccm (and the
id-aesN-ccm names) over OpenSSL's ccm128 steps. They follow Node's tag and
IV lengths, the plaintextLength requirement, the message-length caps and
the one-update rule, and report a failed authentication from final().

They also support the RFC 3394 and RFC 5649 key wrap ciphers (aes-N-wrap,
aesN-wrap, id-aesN-wrap, the -pad forms and the -inv ciphers) over
wrap128.c's routines, with Node's lengths, integrity failures and
one-update rule.

The new names follow the existing ones in the cipher table, so the lookup
cost of the existing ciphers is unchanged.
2026-10-22 17:18:54 -05:00
Chris Tate 20f4d1ff12 Support the legacy createCipheriv modes and crypto.checkPrime/generatePrime 2026-10-22 09:08:35 -05:00
Chris Tate e6115f87e8 Merge main 2026-10-22 07:22:32 -05:00
Chris Tate 714dbfe2bb Merge main 2026-10-22 06:59:47 -05:00
Chris Tate 75bcf9dfa7 Merge main 2026-10-22 06:55:45 -05:00
Chris Tate df6de14c94 Support new tls.TLSSocket and tls.connect({ socket }) (#1791) 2026-10-22 06:01:47 -05:00
Chris Tate 3cefd421a1 Fence requestCert beside a secureContext and free failed TLSSockets
new tls.TLSSocket(socket, { isServer: true, secureContext, requestCert:
true }) skipped the options walk that refuses requestCert, so the server
asked for no client certificate and accepted every client, even with
rejectUnauthorized: true. With a secureContext, Node still reads the
socket's own options, so a truthy requestCert, SNICallback and
ALPNCallback now throw the fence there too.

A TLS socket's transport kept its 'secure' and 'session' listeners until
the socket was freed. A handshake that fails never fires 'secure', so a
listener that captures the socket kept the socket and its TLS state alive
after it closed. The transport now drops those listeners when the socket
settles, and ignores listeners added after that.
2026-10-22 05:58:32 -05:00
Chris Tate 01a467060b Support WebCrypto wrapKey and unwrapKey
crypto.subtle.wrapKey exports a secret key (raw, raw-secret or jwk) and
encrypts it, and unwrapKey decrypts and imports one, as Node's
webcrypto.js does: the wrap algorithm normalizes through the wrapKey
registry (AES-KW) and then the encrypt registry (AES-GCM, AES-CBC and
AES-CTR with their dictionaries), the wrapping key's algorithm and
usages are checked, and a JWK payload is its JSON text, padded with
spaces to a multiple of 8 bytes for AES-KW. A wrapped JWK that is not
UTF-8 JSON with a kty member rejects with Node's DataError.

AES-KW is RFC 3394 key wrap over the vendored mbedTLS block cipher, in
scr_webcrypto_aes.c beside the other AES modes: wrapping takes a
multiple of 8 bytes and at least 16, unwrapping a multiple of 8 and at
least 24, and the integrity check value is compared in constant time.
The cipher's failures, and unwrapKey's import errors, reject on a later
loop turn as Node's job promises do.

This completes jose's symmetric key management: 7132 runs the real
jose 6.2.12 PBES2-HS256+A128KW, PBES2-HS384+A192KW, PBES2-HS512+A256KW,
A128KW and A256KW paths (EncryptJWT and jwtDecrypt) against Node.
getPublicKey replaces wrapKey as the refused method in the fenced
fixture and the JavaScript refusal test.
2026-10-22 05:48:30 -05:00
Chris Tate 1360830149 Support new tls.TLSSocket and tls.connect({ socket }) 2026-10-22 04:52:44 -05:00
Chris Tate 6e753cd5c8 Merge main 2026-10-22 04:08:52 -05:00
Chris Tate b5fb4115e1 Merge main 2026-10-22 03:33:29 -05:00
Chris Tate 1773ffbef3 WebCrypto: the crypto global, node:crypto's webcrypto, and secret-key SubtleCrypto 2026-10-22 02:52:01 -05:00
Chris Tateandsaboursepideh 1a240fbf10 Support asymmetric keys, signatures and Ed25519 in node:crypto and WebCrypto
Co-authored-by: saboursepideh <25549001+saboursepideh@users.noreply.github.com>
2026-10-22 02:49:33 -05:00
Chris Tate 054cb50ea4 Array keys and properties: non-index number keys, Object.keys, console.log 2026-10-22 02:31:20 -05:00
Chris Tate 283a504fe0 Support crypto.createDiffieHellman and getDiffieHellman
crypto.createDiffieHellman, crypto.getDiffieHellman and
crypto.createDiffieHellmanGroup return native DiffieHellman and
DiffieHellmanGroup handles backed by mbedTLS bignums. generateKeys,
computeSecret, getPrime, getGenerator, getPublicKey, getPrivateKey,
setPublicKey, setPrivateKey and verifyError follow Node 24.22:

- the modp1, modp2, modp5 and modp14 through modp18 groups, with the
  private key widths of Node's OpenSSL 3 path (200 to 400 bits for
  modp5 and up, [2, p - 2] for modp1 and modp2);
- explicit primes and generators in every argument form and encoding,
  with keys of bits(p) - 2 bits, or below min(2^N, q) when the
  parameters equal an OpenSSL named group (RFC 3526, RFC 7919,
  RFC 5114);
- generated safe primes with OpenSSL's congruences for the generator;
- verifyError's DH_check bits, computed when it is first read;
- Node's argument, generator, modulus, key range, state and encoding
  errors, including the OpenSSL errors' library and reason properties.

Safe-prime generation sieves candidates with the odd primes below a
bound that grows with the prime's length and tests them with
Miller-Rabin rounds over a variable-time Montgomery exponentiation that
only reads public values; key and secret exponentiations stay on
mbedTLS's constant-time path. Primes longer than 8192 bits, property
reads other than verifyError, property writes, Object.prototype methods,
and calls whose output encoding is typed any or matches no @types/node
overload are refused.

The runtime unit scr_dh.c links, with the mbedTLS archive, only into
programs that use DiffieHellman. wasm32-wasi builds refuse it. The ECDH
unit's argument and encoding helpers move to scr_crypto_args.h, which
both units include.
2026-10-21 21:55:47 -05:00
Chris Tate 0950725949 Refuse elements on Array.prototype 2026-10-21 17:24:17 -05:00
Chris Tate 08c7930958 Support crypto.createECDH and ECDH.convertKey (#1589) 2026-10-20 20:18:22 -05:00
Chris Tate 4e80351f87 Merge main 2026-10-20 19:53:23 -05:00
Chris Tate 2582e46e76 Support crypto.createECDH and ECDH.convertKey
crypto.createECDH returns a native ECDH handle backed by mbedTLS for
prime192v1, secp224r1, prime256v1, secp384r1, secp521r1, secp192k1,
secp224k1, secp256k1, brainpoolP256r1, brainpoolP384r1 and
brainpoolP512r1. generateKeys, computeSecret, getPublicKey,
getPrivateKey, setPrivateKey, setPublicKey and ECDH.convertKey follow
Node 24: compressed, uncompressed and hybrid points, input and output
encodings, the private key range, key pair validation, and Node's error
codes and messages.

Curve names follow OpenSSL's short-name lookup: names of other curves
from crypto.getCurves() are refused at compile time when literal and
throw a coded SC2020 error when computed, other OpenSSL short names
throw ERR_CRYPTO_OPERATION_FAILED, and unknown names throw
ERR_CRYPTO_INVALID_CURVE. Calls whose arguments no @types/node overload
accepts, and computeSecret(view, encoding), are refused at compile time.

The runtime unit scr_ecdh.c links, with the mbedTLS archive, only into
programs that use ECDH. wasm32-wasi builds refuse it.
2026-10-20 19:17:05 -05:00
Chris Tate 450c8ac2a5 Gate thenable adoption on then fields, keep Promise.prototype bindings checked, and cache the gate on the lowerer 2026-10-20 17:59:43 -05:00
Chris Tate e0d14fefaa Merge main 2026-10-20 12:55:55 -05:00