Commit Graph
48730 Commits
Author SHA1 Message Date
James M Snell f378cfcfbf src,lib: add --allow-env permission
Necessarily semver-major.

When `--permission` is on, every env var not matched by
`--allow-env` is removed at startup. It takes names,
prefix patterns (`PREFIX_*`), or `*`, repeatable or
comma-sep'd.

There are a range of env vars that Node.js itself uses,
and a default range that are generally known to be safe
in common usage. These are never scrubbed. These include
things like `NODE_OPTIONS`, `NODE_EXTRA_CA_CERTS`, `PATH`,
`HOME`, etc. `NODE_ENV` is not in the defaults and must
be allowed explicitly.

Proxy vars (`HTTP_PROXY`, `HTTPS_PROXY`, `NO_PROXY`) are
also not in the defaults since they can carry credentials.
When `--use-env-proxy` or `NODE_USE_ENV_PROXY` is set and
any of them were removed, a single warning naming them is
emitted.

Env vars can be dropped at runtime after reading using
`permission.drop()`. This is a stronger protection than
using `process.env.FOO = undefined` because it will
scrub the env var also from the environment block.

On Linux, the removed entries are overwritten in the
initial environment block. fs reads of any other
process's /proc/<pid>/environ, ancestors included, are
denied regardless of `--allow-fs-read`. A process's own
is readable only with `--allow-env=*`. Symlinks are
resolved before the check so paths like
/dev/fd/../../<ppid>/environ are caught. The check only
canonicalizes paths that statfs() reports are on procfs.

On Windows, removal also clears the C runtime's copy
of the environ using _wputenv_s.

Reading a removed name returns undefined, warns once per
name, and publishes to a diagnostics channel.

Env file keys are allowed. If the user had reason to pass
in an env file the assumption is they meant to allow them.

File-source config (node.config.json and NODE_OPTIONS
from a .env file) can only narrow the allow list.

Embedders must call ScrubProcessEnvironment() themselves
on startup. This is left up to the embedder to determine
the exact timing but needs to be called before startup
actually happens.

Child processes are started with `--allow-env=*`. Those
either receive the explicit env they were started with
or only the env they inherit from the parent. Since the
parent process is scrubbed, and the child cannot read
any other process's /proc/<pid>/environ, it should never
see more than the parent can.

Main part of the impl was done by hand. Docs, tests,
verification pass, and cleanup nits were automated.

Signed-off-by: James M Snell <jasnell@gmail.com>
Assisted-by: Opencode
PR-URL: https://github.com/nodejs/node/pull/66132
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
2026-09-26 21:18:43 +00:00
Lazizbek Ergashev 261c8a196c events: fix addAbortListener for aborted signals
Signed-off-by: Lazizbek Ergashev <lazerg2@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/65640
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Robert Nagy <ronagy@icloud.com>
2026-09-26 20:55:09 +00:00
Ilyas Shabi cf072ab0cd src: expose size and count in heap profile output
Signed-off-by: ishabi <ilyasshabi94@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/65737
Reviewed-By: Anna Henningsen <anna@addaleax.net>
2026-09-26 20:46:13 +00:00
Yagiz NizipliandYagiz Nizipli 6a6e09e834 querystring: speed up default parse and unescape
Skip the %XX walk in unescapeBuffer when the input has no '%'.
Add a dedicated '&'/'=' scanner for the default parse path so
it does not build separator code arrays or run the multi-char
state machine.

Official benchmark/querystring/querystring-parse.js:
encodemany is about 38% faster, manyblankpairs about 17%,
encodelast about 10%, noencode about 8%.
Official querystring-unescapebuffer.js with no escapes is
about 36% faster.

Assisted-by: a closed-source coding agent
Signed-off-by: Yagiz Nizipli <yagiz@nizipli.com>
Co-authored-by: Yagiz Nizipli <anonrig@users.noreply.github.com>
PR-URL: https://github.com/nodejs/node/pull/66175
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
2026-09-26 20:34:53 +00:00
Maya Lekova d35c89e03d test: add smoke tests for defer importing synthetic modules
The tests added ensure that Node.js doesn't crash or produce
incorrect results when importing synthetic modules (i.e. JSON,
text or builtin modules) with the `defer` modifier.

Signed-off-by: Maya Lekova <maya@igalia.com>
PR-URL: https://github.com/nodejs/node/pull/65537
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
2026-09-26 19:53:05 +00:00
Christian Aurich Zanettini Martins 1e17275dea fs: fix crash on negative zero file descriptor
`isInt32()` accepts -0 because `-0 === (-0 | 0)`, but V8 does not
represent -0 as an Int32 value, so `Value::IsInt32()` rejects it. The
utf8 fast paths of `readFileSync()` and `writeFileSync()` hand the value
straight to the binding, which then took it for a path and aborted on
the null check.

Coerce -0 to 0 before the call, matching `getValidatedFd()` and the rest
of fs, where -0 is a valid way to name file descriptor 0.

Signed-off-by: Christian Aurich <christian.aurichzm@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/65888
Fixes: https://github.com/nodejs/node/issues/65886
Reviewed-By: Xuguang Mei <meixuguang@gmail.com>
2026-09-26 19:52:53 +00:00
Dayun d9208ccdcc worker: remove messageerror listeners on exit
Signed-off-by: Dayun <dlekdbs6530@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/66075
Fixes: https://github.com/nodejs/node/issues/65782
Reviewed-By: James M Snell <jasnell@gmail.com>
2026-09-26 19:42:29 +00:00
Dayun 31e841f056 stream: fix pipeline function tail deadlock
Signed-off-by: Dayun <dlekdbs6530@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/65559
Fixes: https://github.com/nodejs/node/issues/40685
Reviewed-By: Robert Nagy <ronagy@icloud.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
2026-09-26 19:32:45 +00:00
Hubert Walczak db1e36b8dd worker: strip types in Web Worker module entries
Strip TypeScript from file-backed module worker entries before
evaluating the fetched source.

Add regression coverage and document the supported entry types.

Assisted-by: Codex
Signed-off-by: Hubert Walczak <hubertwalczak8@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/66085
Reviewed-By: Aviv Keller <me@aviv.sh>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matthew Aitken <maitken033380023@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
2026-09-26 18:28:17 +00:00
Xia Chao 1e0167d7d6 zlib: preserve brotli params and dictionary on reset
ResetStream currently calls Init() with no arguments, which drops
the stored dictionary and never replays SetParams. Remember each
successful parameter and replay both the dictionary and the params
when the stream is reset.

Fixes: https://github.com/nodejs/node/issues/66156
Signed-off-by: Xia Chao <shapirolutts@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/66157
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
2026-09-26 18:28:05 +00:00
Xia Chao ca0810fd80 zlib: reject reset after gzip/deflate emitted incomplete output
deflateReset starts a new member. Bytes already written out cannot be
taken back, so gunzip/inflate see a truncated member followed by a new
header. Refuse reset in that case. Raw deflate has no wrapper header
and is unchanged.

Signed-off-by: Xia Chao <shapirolutts@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/66179
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
2026-09-26 18:27:53 +00:00
Tim Perry af13502159 benchmark: fix shadowing that broke h=20 on incoming_headers benchmark
Previously the inner 'headers' variable shadowed the outer, meaning that
headers=20 sends the same 7 headers as headers=0.

Signed-off-by: Tim Perry <pimterry@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/66257
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
2026-09-26 18:27:41 +00:00
Chengzhong Wu 71c63912a7 build: add clang support for pgo on macOS/Linux
Signed-off-by: Chengzhong Wu <legendecas@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/66136
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
2026-09-26 17:19:09 +00:00
Eliau Elkouby 08dbed2272 deps: V8: backport 786c1c2d88d4
Original commit message:

    [stack-traces] Fix overflow in Error.stackTraceLimit trimming

    When stack traces are captured for uncaught exceptions (enabled via
    Isolate::SetCaptureStackTraceForUncaughtExceptions, e.g. by the
    inspector or by Node.js's --trace-uncaught), CaptureAndSetErrorStack
    reuses the simple stack trace and trims it to Error.stackTraceLimit.

    Error.stackTraceLimit counts frames, but the raw call site data stores
    CallSiteInfo::Fields::kCount slots per frame, so the trim multiplied the
    limit by kCount: once in the uint32_t comparison against the array
    length and once, as int, to compute the new length. GetStackTraceLimit
    clamps the limit to [0, INT_MAX], so for very large limits the uint32_t
    product can wrap to a value below the array length. The trim branch is
    then taken although the limit exceeds the number of captured frames,
    and the int multiplication of the new length overflows.

    On main (kCount == 5) the product first wraps at 858993460. That limit
    trimmed the raw data to 4 slots (no complete frame) and 858993461 to 9
    slots (one frame), so error.stack silently lost frames. Infinity, the
    value from the Node.js report, is clamped to INT_MAX; its wrapped
    product (2147483643) is not below the array length, so on main it does
    not take the trim branch and does not reach the signed overflow.

    Fix this by comparing the limit with the number of frames in the raw
    data (length / kCount), and only multiplying once the limit is known to
    be smaller than the frame count. The resulting length is then bounded
    by the existing array length and cannot overflow. Behavior for limits
    that did not overflow is unchanged, since the raw data length is always
    a multiple of kCount.

    This regressed with https://crrev.com/c/7673818 (ebd15783b7b,
    "[objects]: Defer CallSiteInfo creation"), which switched from one
    CallSiteInfo per frame to kCount raw slots per frame.

    This is the underlying cause of Node.js issue 66074. The symptom there
    differs from main: Node's V8 14.6 backport of that change has
    kCount == 6 and uses int for the comparison and for RightTrim, so the
    product overflows for limits above 357913941. For many of those,
    including Infinity (INT_MAX * 6 wraps to -6), the result is negative
    and fails "Check failed: new_capacity > 0." in RightTrim. Comparing in
    frames avoids the overflow in both cases.

    The new cctest CaptureStackTraceForUncaughtExceptionHugeStackTraceLimit
    enables capture for uncaught exceptions and checks that limits of
    858993460, 858993461 and Infinity yield the same error.stack as a limit
    of 10, and that a limit of 1 still trims to a single frame. 858993460
    and 858993461 are the first limits whose product with kCount wraps
    around uint32_t; both fail without this change. The new test and the
    existing stack trace tests also pass in a UBSan build, with no
    diagnostics.

    Bug: 565047704
    Refs: https://github.com/nodejs/node/issues/66074
    Change-Id: I3422ca1de6a7dd9448c7fd53fb9bc5e40e2a17c1
    Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/8426465
    Reviewed-by: Patrick Thier <pthier@chromium.org>
    Reviewed-by: Leszek Swirski <leszeks@chromium.org>
    Auto-Submit: eliau elkouby (‫אליהו אלקובי‬‎) <eliau.elkouby@gmail.com>
    Commit-Queue: Patrick Thier <pthier@chromium.org>
    Cr-Commit-Position: refs/heads/main@{#110043}

Refs: https://github.com/v8/v8/commit/786c1c2d88d445eecf54efe7ba9cef27a3eef3bb
Fixes: https://github.com/nodejs/node/issues/66074
Assisted-by: a closed-source coding agent
Signed-off-by: Eliau Elkouby <145869377+eliau2005@users.noreply.github.com>
PR-URL: https://github.com/nodejs/node/pull/66249
Reviewed-By: René <contact.9a5d6388@renegade334.me.uk>
Reviewed-By: Richard Lau <richard.lau@ibm.com>
2026-09-26 16:27:28 +00:00
Efe Karasakal c0681e5179 http: normalize CONNECT request paths
Signed-off-by: Efe Karasakal <hi@efe.dev>
PR-URL: https://github.com/nodejs/node/pull/64876
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Tim Perry <pimterry@gmail.com>
2026-09-26 14:02:54 +00:00
Node.js GitHub Bot 95279e7af8 deps: update googletest to 4267679b6887f349f17b01ccd70c9e3483689b25
PR-URL: https://github.com/nodejs/node/pull/66145
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Aviv Keller <me@aviv.sh>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
2026-09-26 12:49:32 +00:00
Filip Skokan 66f26d3a9b test: deflake test runner timeout coverage
Use a dedicated fixture with a pending promise and assertion plan
instead of competing assertion timers. Keep both timeout failure
assertions and clear the keepalive interval after the tests finish.

Signed-off-by: Filip Skokan <panva.ip@gmail.com>
Assisted-by: Codex
PR-URL: https://github.com/nodejs/node/pull/66255
Reviewed-By: Aviv Keller <me@aviv.sh>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
2026-09-26 08:20:30 +00:00
Filip Skokan 4cd4701f69 test: deflake inspector async hook setup
Async hook activation can be deferred when the inspector command arrives
during a V8 interrupt. Schedule timeout creation with setImmediate so
the event loop finishes enabling the hooks before recording its async
stack.

Signed-off-by: Filip Skokan <panva.ip@gmail.com>
Assisted-by: Codex
PR-URL: https://github.com/nodejs/node/pull/66255
Reviewed-By: Aviv Keller <me@aviv.sh>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
2026-09-26 08:20:29 +00:00
Tim Perry 5d9228d5c3 tools: pin sccache on all platforms to fix benchmark CI job
Signed-off-by: Tim Perry <pimterry@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/66284
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
2026-09-26 08:20:18 +00:00
Filip Skokan 45fef372fc test: deflake debugger function name extraction
Evaluating expressions against the running target can trigger a V8
scope assertion. Keep the target paused and wait for the initial break
before checking the function formatting. Await debugger teardown.

Signed-off-by: Filip Skokan <panva.ip@gmail.com>
Assisted-by: Codex
PR-URL: https://github.com/nodejs/node/pull/66231
Reviewed-By: Aviv Keller <me@aviv.sh>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
2026-09-26 07:57:16 +00:00
Yagiz Nizipli 4889fb0a43 stream: skip write() checks in flowing pipe
pipe() installs one 'data' listener that calls dest.write() for
every chunk. That repeats encoding, mode, and end checks that stay
the same for a synchronous buffer write.

When that listener is still the only one, hand the Buffer to the
same synchronous write path without those checks. A second
listener, a non-buffer chunk, or a busy writable still goes through
emit('data').

On top of the flowing-read fast path, benchmark/streams/pipe.js is
about 31% faster (20 runs). Object-mode pipe and readable-readall
stay within noise.

Assisted-by: a closed-source coding agent
Signed-off-by: Yagiz Nizipli <yagiz@nizipli.com>
PR-URL: https://github.com/nodejs/node/pull/66182
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Robert Nagy <ronagy@icloud.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Zeyu "Alex" Yang <himself65@outlook.com>
2026-09-26 06:47:49 +00:00
Yagiz Nizipli 236b53ff62 stream: speed up flowing pipe of buffers
flow() pulls one already-buffered chunk and calls _read() for the
next one on every iteration. That goes through the general read()
path, which updates a holey buffer array and then pulls the chunk
back out.

While a synchronous byte-mode flow is in progress, keep that
prefetched chunk on the readable state and emit it directly.
_read() of the next chunk still runs before 'data', and a nested
read() moves the chunk back onto the buffer.

benchmark/streams/pipe.js is about 77% faster (15 runs).
pipe-object-mode, readable-readall, and readable-bigread stay
within noise.

Assisted-by: a closed-source coding agent
Signed-off-by: Yagiz Nizipli <yagiz@nizipli.com>
PR-URL: https://github.com/nodejs/node/pull/66182
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Robert Nagy <ronagy@icloud.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Zeyu "Alex" Yang <himself65@outlook.com>
2026-09-26 06:47:48 +00:00
inoway46 ebd52388a4 tools: reduce source tarball compression in CI
Use gzip level 6 in build-tarball and test-shared to reduce tarball
creation time with a small increase in archive size.

Refs: https://github.com/nodejs/node/pull/66228#issuecomment-5822882231
Assisted-by: Codex
Signed-off-by: inoway46 <inoueyuya416@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/66228
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
2026-09-26 06:47:36 +00:00
inoway46 733bb345f0 build: add GZIP_COMPRESSION Make variable
Make gzip compression configurable for source, header, and binary
tarballs. Keep level 9 as the default.

Assisted-by: Codex
Signed-off-by: inoway46 <inoueyuya416@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/66228
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
2026-09-26 06:47:35 +00:00
Trivikram Kamat 38ad98a0ae test: use Database in sqlite virtual table test
The sqlite classes were renamed from DatabaseSync to Database.
The file now imports only `Database`, but the "closes the iterator when
a filter is reapplied to the cursor" test landed with a leftover
`new DatabaseSync()` call, which throws a ReferenceError.

Signed-off-by: Trivikram Kamat <16024985+trivikr@users.noreply.github.com>
PR-URL: https://github.com/nodejs/node/pull/66307
Refs: https://github.com/nodejs/node/pull/65988
Reviewed-By: Daeyeon Jeong <daeyeon.dev@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
2026-09-26 08:36:34 +02:00
Trevor Burnham 8812357aff src: throw on a malformed localStorage file
The localStorage backing file is a user-specified path, and the schema
is created with CREATE TABLE IF NOT EXISTS, so a file that already
contains tables of those names is adopted as-is. Its stored values may
then have any SQLite type, but every read asserted the expected type
with CHECK, so a wrong-typed value aborted the process. A bad
schema_version was the worst case: that assertion is in
Storage::Open(), so any access aborted and the application had no
chance to inspect or repair the file.

Report these as ERR_INVALID_STATE instead, matching the throw four
lines below the schema_version assertion for a version that is too new.
Storage::GetAll() has no JavaScript caller to throw at, so it returns
std::nullopt and the DOM storage inspector agent reports a protocol
error.

Now that a failed open returns instead of aborting, Open() has to clean
up after itself: adopt the sqlite3* into a conn_unique_ptr immediately,
so that an error does not leak the connection and leave the next access
to open another one.

Storage::GetAll() also ignored the result of sqlite3_prepare_v2() and
the status its row loop ended on, reporting a malformed file or a
mid-scan error as an empty store. Both now return std::nullopt.

Also drop a redundant second sqlite3_exec() of the init SQL that
clobbered the result of the sqlite3_prepare_v2() above it, hiding
prepare failures behind a misleading "bad parameter or other API
misuse".

Signed-off-by: Trevor Burnham <trevorburnham@gmail.com>
Assisted-by: Claude Opus 5
PR-URL: https://github.com/nodejs/node/pull/65879
Fixes: https://github.com/nodejs/node/issues/65878
Fixes: https://github.com/nodejs/node/issues/64640
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
2026-09-26 02:30:46 +00:00
Guilherme Araújo f2b698f1cf sqlite: rename DatabaseSync and StatementSync
Rename the DatabaseSync and StatementSync classes to Database and
Statement, and the internal DatabaseSyncLimits helper to
DatabaseLimits. The old names are kept as aliases of the new classes
and are Documentation-only deprecated (DEP0210, DEP0211).

Assisted-by: Claude Code
Signed-off-by: Guilherme Araújo <arauujogui@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/65988
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Robert Nagy <ronagy@icloud.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
2026-09-26 00:03:45 +00:00
Matteo Collina 9c06dab7d0 http: pass maxHeaderPairs to parser.initialize()
The parser read the `maxHeaderPairs` property from its JS object in
C++ once per header section to enforce the header count limit. That
lookup is a runtime property load for every parsed request, and costs
up to 7% on the parser benchmark for requests with few headers.

Pass the limit to `initialize()` instead and keep it in a field. The
property is still set, as the JS side uses it to trim the header list.

Refs: https://github.com/nodejs/node/pull/64988
Signed-off-by: Matteo Collina <hello@matteocollina.com>
PR-URL: https://github.com/nodejs/node/pull/66250
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Gürgün Dayıoğlu <hey@gurgun.day>
Reviewed-By: Xuguang Mei <meixuguang@gmail.com>
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: Tim Perry <pimterry@gmail.com>
Reviewed-By: Gerhard Stöbich <deb2001-github@yahoo.de>
2026-09-25 21:29:33 +00:00
Yagiz Nizipli 4bd56b3590 http: avoid toLowerCase on the server hot path
After #65802, Host/Expect/body checks still allocate
toLowerCase() copies and Expect/HTTP/1.0 TE still
read req.headers. Compare names without allocating,
read those values from rawHeaders, intern parser
header names, and skip Title-Case toLowerCase on
common outgoing fields.

Refs: https://github.com/nodejs/node/pull/65802
Signed-off-by: Yagiz Nizipli <yagiz@nizipli.com>
Assisted-by: a closed-source coding agent
PR-URL: https://github.com/nodejs/node/pull/66120
Refs: https://github.com/nodejs/node/pull/65332
Reviewed-By: Robert Nagy <ronagy@icloud.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
2026-09-25 20:47:42 +00:00
James M Snell 823d229adc src: add --process-timeout=N
Putting a time limit on a Node.js process is common in many
use cases, but each of the common approaches are generally
flawed.

OS and CI timeouts are inconsistent and blind. Every OS flavor
handles process timeouts in different ways. Stock macOS and
Windows do not ship coreutils `timeout`, etc. None of the options
can explain why the process was still running or what exactly
was interrupted. Using setTimeout only fires when the event loop
is free so it misses busy loops and thread blocks and cannot
see the stack. Diagnostics triggered by signal have the same
problem.

This introduces a `--process-timeout` that should work
consistently across all runtimes. A native watchdog thread
interrupts the main thread, even in the middle of running
code. It prints the JavaScript stack (if any) and resources
keeping the event loop alive (if any), and can optionally
print a full diagnostic report. The process exits with a
distinct code (124). If the main thread is stuck in native
code, the process still exits.

    $ node --process-timeout=10s -e "while(true) {}"
    (node:483970) Process timed out after 10s (--process-timeout). Exiting with code 124.
    Main thread was executing JavaScript:
        at [eval]:1:1
        at runScriptInThisContext (node:internal/vm:219:10)
        at node:internal/process/execution:485:12
        at [eval]-wrapper:6:24
        at runScriptInContext (node:internal/process/execution:483:60)
        at evalFunction (node:internal/process/execution:317:30)
        at evalTypeScript (node:internal/process/execution:329:3)
        at node:internal/main/eval_string:71:3
    No resources keeping the event loop alive were found.

Signed-off-by: James M Snell <jasnell@gmail.com>
Assisted-by: Opencode
PR-URL: https://github.com/nodejs/node/pull/66138
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
2026-09-25 20:28:33 +00:00
Christian Aurich Zanettini Martins cc610f1cfb fs: validate falsy openAsBlob type option
openAsBlob() and openAsBlobSync() read the MIME type as
options.type || '' before validating it, causing falsy non-string
values to be replaced with the default before reaching validateString().
As a result, { type: 0 }, { type: false }, { type: null }, and
{ type: NaN } are accepted as an empty type, while { type: 1 }
throws ERR_INVALID_ARG_TYPE.

Default the option only when it is undefined so all other values are
validated against the documented string type.

Signed-off-by: Christian Aurich Zanettini Martins <christian.aurichzm@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/66125
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
2026-09-25 19:44:48 +00:00
Christian Aurich Zanettini Martins 63a6ea26bb ffi: reject non-boolean copy arguments
ffi.toBuffer() and ffi.toArrayBuffer() document copy as a boolean, but
read it with BooleanValue(), which applies JavaScript truthiness. A
falsy non-boolean such as null, 0 or '' therefore selects the
zero-copy mode, which returns a writable view over foreign memory
instead of a copy, while values such as 'false' or 1 select a copy.

Throw ERR_INVALID_ARG_TYPE when copy is neither undefined nor a
boolean. Omitting copy or passing undefined still makes a copy, and
true and false keep their current behavior.

Signed-off-by: Christian Aurich Zanettini Martins <christian.aurichzm@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/66219
Reviewed-By: Daeyeon Jeong <daeyeon.dev@gmail.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
2026-09-25 21:33:44 +02:00
agape1225 118f2a1d78 stream: support ArrayBufferView in Utf8Stream write() buffer mode
Utf8Stream#write() in 'buffer' content mode only accepted Buffer
instances, even though the underlying implementation only needs
byte-addressable data. This accepts any ArrayBufferView (TypedArray,
DataView) and reinterprets it as a Buffer over the same bytes
(without copying), so callers no longer need to wrap other typed
arrays in Buffer.from() themselves.

Views are normalized to a Buffer at the single entry point
(#writeBuffer), using byteOffset/byteLength rather than the view's
element-count length, so that internal length bookkeeping used by
mergeBuf()/Buffer.concat() and the write-release logic keeps
operating on real byte counts. This mirrors the existing pattern in
zlibBuffer() (lib/zlib.js).

Signed-off-by: agape1225 <49804691+agape1225@users.noreply.github.com>
PR-URL: https://github.com/nodejs/node/pull/65301
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
2026-09-25 21:32:36 +02:00
XadillaX 5ebf690dcf http: preserve socket errors as response error causes
Keep the original socket error as the cause of ECONNRESET errors emitted
when an HTTP response closes before completion. Preserve the existing
aborted message, error code, and event order. Leave cause absent when
there is no underlying error.

Allow ConnResetException to accept Error options, document the behavior,
and cover TLS record errors, TCP resets, explicit destruction, and
premature closure without a socket error.

This follows investigation of #66001 and addresses lost error context.
The original TLS decryption failure remains unresolved.

Refs: https://github.com/nodejs/node/issues/66001
Signed-off-by: XadillaX <i@2333.moe>
PR-URL: https://github.com/nodejs/node/pull/66061
Reviewed-By: Robert Nagy <ronagy@icloud.com>
Reviewed-By: Tim Perry <pimterry@gmail.com>
2026-09-25 21:31:04 +02:00
Donghoon Kang ad63e9ef29 ffi: use type errors for invalid signatures
Signed-off-by: HoonDongKang <d159123@naver.com>
PR-URL: https://github.com/nodejs/node/pull/66222
Reviewed-By: Daeyeon Jeong <daeyeon.dev@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
2026-09-25 18:58:21 +00:00
agape1225 e76358e3f1 src: reserve shared_array_buffers capacity in Message::Deserialize
shared_array_buffers grows via repeated push_back() while iterating
shared_array_buffers_, even though shared_array_buffers_.size() is
already known before the loop starts and is an exact count of how
many items will be pushed (one per iteration, unconditionally).
This reserves capacity upfront to avoid the repeated allocate/copy/
free cycle that happens each time capacity is exceeded, mirroring
the existing array_buffers.reserve() in the sibling
Message::Serialize().

Signed-off-by: agape1225 <49804691+agape1225@users.noreply.github.com>
PR-URL: https://github.com/nodejs/node/pull/65304
Reviewed-By: James M Snell <jasnell@gmail.com>
2026-09-25 18:49:51 +00:00
James M Snell 990aefdf56 lib: fix stream loading bug in node:bench
Not all of the stream APIs are correctly loaded until
the `node:stream` module is loaded.

Signed-off-by: James M Snell <jasnell@gmail.com>
Assisted-by: Opencode
PR-URL: https://github.com/nodejs/node/pull/66114
Fixes: https://github.com/nodejs/node/issues/41641
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
2026-09-25 18:49:36 +00:00
James M Snell a2dedccee0 perf_hooks: allow RecordableHistogram to record 0
Previously the lowest value accepted was 1.

Signed-off-by: James M Snell <jasnell@gmail.com>
Assisted-by: Opencode
PR-URL: https://github.com/nodejs/node/pull/66114
Fixes: https://github.com/nodejs/node/issues/41641
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
2026-09-25 18:49:35 +00:00
Junhwan Choi d78337f085 test: use spawnSync helpers in cpu-prof tests
The cpu-prof tests hand-rolled a partial version of what
test/common/child_process already provides: log the child's stderr
when the status is non-zero, then assert the status. That manual
version never shows stdout, the signal, or the command that ran, so
a CI failure gives less information than the helper would.

Replace those blocks with spawnSyncAndExitWithoutError(). Every
existing expectation is preserved -- status 0 is still required, and
signal null is now checked as well, matching the helper defaults.

Only success-path blocks whose assertions map one-to-one onto the
helper defaults are converted.

Refs: https://github.com/nodejs/node/pull/65351
Refs: https://github.com/nodejs/node/pull/65552
Assisted-by: claude:opus-5
Signed-off-by: Junhwan Choi <devjunsday@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/65694
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
2026-09-25 20:49:20 +02:00
Kamat, Trivikram 8bf65d4beb sqlite: run generator return() on cursor refilter
SQLite re-invokes xFilter on a cursor it already used, as it does
for the inner table of a correlated subquery or join, abandoning the
previous iterator mid-loop. Call its return() method so generator
`finally` blocks still run.

Refactor the xClose cleanup intoCloseIterator() so both paths share it;
on refilter, a throwing cleanup is surfaced as the query error.

Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com>
Assisted-by: opencode
PR-URL: https://github.com/nodejs/node/pull/66195
Fixes: https://github.com/nodejs/node/issues/66193
Reviewed-By: Guilherme Araújo <arauujogui@gmail.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
2026-09-25 20:43:00 +02:00
Soul Lee 6c59f35957 ffi: allocate string argument storage lazily
Reserve temporary string storage in InvokeFunction only when the
first string argument is encountered. Calls without string arguments
avoid allocating and freeing an unused vector buffer.

Reserve capacity for all arguments before saving the first string
pointer so subsequent strings cannot invalidate it. Add coverage for
multiple strings, mixed Buffer arguments, and errors during argument
conversion.

Signed-off-by: Soul Lee <alus20x@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/66178
Reviewed-By: Daeyeon Jeong <daeyeon.dev@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
2026-09-25 17:34:13 +00:00
James M Snell 3ca944c1f4 src: ensure Socket(fd) cannot bypass allow-net permission
Signed-off-by: James M Snell <jasnell@gmail.com>
Assisted-by: Opencode
PR-URL: https://github.com/nodejs/node/pull/66117
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
2026-09-25 17:21:04 +00:00
Noah 96ee81c708 doc,src,test: fix typos in code comments
Correct miscellaneous spelling and grammar typos in code comments and
documentation. No code identifiers or runtime logic were modified.

Signed-off-by: Noah Webber <noah.webber@pmg.com>
Assisted-by: Gemini
PR-URL: https://github.com/nodejs/node/pull/66218
Reviewed-By: Tim Perry <pimterry@gmail.com>
Reviewed-By: Filip Skokan <panva.ip@gmail.com>
2026-09-25 18:14:48 +02:00
Thomas Hunter II 53aafbb4c2 util,assert: expose util.isPartialDeepStrictEqual()
Signed-off-by: Thomas Hunter II <tlhunter@datadog.com>
PR-URL: https://github.com/nodejs/node/pull/66118
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
2026-09-25 15:36:32 +00:00
Yagiz Nizipli bc6e1ad8f9 net: speed up BlockList.check for strings
Skip toLowerCase() for the documented ipv4/ipv6 families and add a
V8 Fast API for one-byte address strings. The FastOneByteString
callback takes FastApiCallbackOptions so V8 can use the fast path
reliably (required for string-shaped Fast API arguments).

Overlong IPv6 zone ids are parsed like uv_ip6_addr (unknown zone
is scope_id 0; address parts 40+ chars stay a miss). IPv4 zone
suffixes stay a miss, matching uv_ip4_addr.

Assisted-by: a closed-source coding agent
Signed-off-by: Yagiz Nizipli <yagiz@nizipli.com>
PR-URL: https://github.com/nodejs/node/pull/66166
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Tim Perry <pimterry@gmail.com>
2026-09-25 14:39:01 +00:00
Filip Skokan b48f24afbd test: reduce expensive crypto test variants
Skip redundant RSA keygen and PBKDF2 WPT variants during regular CI.
Keep the full matrix when producing a WPT report.

Use fewer scrypt, PBKDF2, and Argon2 derivations in parallel tests.
Reuse RSA key material across OAEP hash and PSS salt tests.

Signed-off-by: Filip Skokan <panva.ip@gmail.com>
Assisted-by: Codex
PR-URL: https://github.com/nodejs/node/pull/66244
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Xuguang Mei <meixuguang@gmail.com>
2026-09-25 14:25:32 +00:00
Jihwan 30c5a6596f test: ensure fsPromises.watch rejects on abort
Signed-off-by: hanityx <hanityx@gmail.com>
PR-URL: https://github.com/nodejs/node/pull/65768
Refs: https://github.com/nodejs/node/pull/58490
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
2026-09-25 13:59:31 +00:00
Yagiz NizipliandYagiz Nizipli 0a36bce53a net: skip IPv6 regex when the string has no colon
IPv6 addresses always contain ':'. Reject IPv4 addresses and
hostnames before running the IPv6 regular expression.

Official benchmark/net/net-is-ip-v6.js is about 27% faster.
net-is-ip-v4.js is unchanged.

Assisted-by: a closed-source coding agent
Signed-off-by: Yagiz Nizipli <yagiz@nizipli.com>
Co-authored-by: Yagiz Nizipli <anonrig@users.noreply.github.com>
PR-URL: https://github.com/nodejs/node/pull/66165
Reviewed-By: Tim Perry <pimterry@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
2026-09-25 13:59:16 +00:00
Steven 9827749bee tls: initialize session and SNI before connecting
A synchronous custom lookup can abort the socket before tls.connect()
applies the session and SNI, leaving the TLS handle unavailable.
Initialize both before starting the connection so the original
socket error is emitted normally.

Assisted-by: Codex
Signed-off-by: Steven <steven@ceriously.com>
PR-URL: https://github.com/nodejs/node/pull/65624
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Tim Perry <pimterry@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
2026-09-25 13:50:11 +00:00
Romain Lanz 464cbbda8a url: create URLSearchParams collision map lazily
Object property keys are already unique unless USVString normalization
changes a key. Avoid allocating and updating a SafeMap for ordinary
record keys. Create and backfill it when normalization first changes a
key.

This improves object construction by 10% to 25% in the measured cases
and reduces allocation by about 31% for a ten-property record.

Assisted-by: Amp
Signed-off-by: Romain Lanz <romain.lanz@pm.me>
PR-URL: https://github.com/nodejs/node/pull/65801
Reviewed-By: James M Snell <jasnell@gmail.com>
2026-09-25 13:49:56 +00:00