Skip to content

Commit 58ddce9

Browse files
committed
Merge remote-tracking branch 'upstream/main' into vfs
2 parents f311fff + 48c208f commit 58ddce9

440 files changed

Lines changed: 9089 additions & 4593 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/lint-release-proposal.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ jobs:
8888
gh api \
8989
-H "Accept: application/vnd.github+json" \
9090
-H "X-GitHub-Api-Version: 2022-11-28" \
91-
--jq '.commits.[] | { smallSha: .sha[0:10] } + (.commit.message|capture("^(?<title>.+)\n\n(.*\n)*PR-URL: (?<prURL>.+)\n"))' \
91+
--jq '.commits.[] | { smallSha: .sha[0:10] } + (.commit.message|capture("^(?<title>.+)\n\n(.*\n)*PR-URL: (?<prURL>.+)(\n|$)"))' \
9292
"/repos/${GITHUB_REPOSITORY}/compare/v${MAJOR}.x...$GITHUB_SHA" --paginate \
9393
| node tools/actions/lint-release-proposal-commit-list.mjs "$CHANGELOG_PATH" "$GITHUB_SHA" \
9494
| while IFS= read -r PR_URL; do

.github/workflows/tools.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ permissions:
5353
jobs:
5454
tools-deps-update:
5555
if: github.repository == 'nodejs/node' || github.event_name == 'workflow_dispatch'
56-
runs-on: ubuntu-slim
56+
# cannot use ubuntu-slim here because some update scripts require Docker
57+
runs-on: ubuntu-latest
5758
strategy:
5859
fail-fast: false # Prevent other jobs from aborting if one fails
5960
matrix:

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ release.
4141
</tr>
4242
<tr>
4343
<td valign="top">
44-
<b><a href="doc/changelogs/CHANGELOG_V25.md#25.7.0">25.7.0</a></b><br/>
44+
<b><a href="doc/changelogs/CHANGELOG_V25.md#25.8.0">25.8.0</a></b><br/>
45+
<a href="doc/changelogs/CHANGELOG_V25.md#25.7.0">25.7.0</a><br/>
4546
<a href="doc/changelogs/CHANGELOG_V25.md#25.6.1">25.6.1</a><br/>
4647
<a href="doc/changelogs/CHANGELOG_V25.md#25.6.0">25.6.0</a><br/>
4748
<a href="doc/changelogs/CHANGELOG_V25.md#25.5.0">25.5.0</a><br/>

SECURITY.md

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -320,9 +320,17 @@ the community they pose.
320320
* Avoid exposing low-level or dangerous APIs directly to untrusted users.
321321

322322
* Examples of scenarios that are **not** Node.js vulnerabilities:
323-
* Allowing untrusted users to register SQLite user-defined functions that can
324-
perform arbitrary operations (e.g., closing database connections during query
325-
execution, causing crashes or use-after-free conditions).
323+
* Allowing untrusted users to register SQLite user-defined functions via
324+
`node:sqlite` (`DatabaseSync`) that can perform arbitrary operations
325+
(e.g., closing database connections during query execution, causing crashes
326+
or use-after-free conditions).
327+
* Loading SQLite extensions using the `allowExtension` option in
328+
`DatabaseSync` — this option must be explicitly set to `true` by the
329+
application, and enabling it is the application operator's responsibility.
330+
* Using `node:sqlite` built-in SQL functions or pragmas (e.g.,
331+
`ATTACH DATABASE`) to read or write files — `DatabaseSync` operates with
332+
the same file-system access as the process itself, and it is the
333+
application's responsibility to restrict what SQL is executed.
326334
* Exposing `child_process.exec()` or similar APIs to untrusted users without
327335
proper input validation, allowing command injection.
328336
* Allowing untrusted users to control file paths passed to file system APIs
@@ -362,6 +370,56 @@ the community they pose.
362370
responsibility to properly handle errors by attaching appropriate
363371
`'error'` event listeners to EventEmitters that may emit errors.
364372

373+
#### Permission Model Boundaries (`--permission`)
374+
375+
The Node.js [Permission Model](https://nodejs.org/api/permissions.html)
376+
(`--experimental-permission`) is an opt-in mechanism that limits which
377+
resources a Node.js process may access. It is designed to reduce the blast
378+
radius of mistakes in trusted application code, **not** to act as a security
379+
boundary against intentional misuse or a compromised process.
380+
381+
The following are **not** vulnerabilities in Node.js:
382+
383+
* **Operator-controlled flags**: Behavior unlocked by flags the operator
384+
explicitly passes (e.g., `--localstorage-file`) is the operator's
385+
responsibility. The permission model does not restrict how Node.js behaves
386+
when the operator intentionally configures it.
387+
388+
* **`node:sqlite` and the permission model**: `DatabaseSync` operates with the
389+
same file-system privileges as the process. Using SQL pragmas or built-in
390+
SQLite mechanisms (e.g., `ATTACH DATABASE`) to access files does not bypass
391+
the permission model — the permission model does not intercept SQL-level
392+
file operations.
393+
394+
* **Path resolution and symlinks**: `fs.realpathSync()`, `fs.realpath()`, and
395+
similar functions resolve a path to its canonical form before the permission
396+
check is applied. Accessing a file through a symlink that resolves to an
397+
allowed path is the intended behavior, not a bypass. TOCTOU races on
398+
symlinks that resolve within the allowed list are similarly not considered
399+
permission model bypasses.
400+
401+
* **`worker_threads` with modified `execArgv`**: Workers inherit the permission
402+
restrictions of their parent process. Passing an empty or modified `execArgv`
403+
to a worker does not grant it additional permissions.
404+
405+
#### V8 Sandbox
406+
407+
The V8 sandbox is an in-process isolation mechanism internal to V8 that is not
408+
a Node.js security boundary. Node.js does not guarantee or document the V8
409+
sandbox as a security feature, and it is not enabled in a way that provides
410+
security guarantees in production Node.js builds. Reports about escaping the V8
411+
sandbox are not considered Node.js vulnerabilities; they should be reported
412+
directly to the [V8 project](https://v8.dev/docs/security-bugs).
413+
414+
#### CRLF Injection in `writeEarlyHints()`
415+
416+
`ServerResponse.writeEarlyHints()` accepts a `link` header value that is set
417+
by the application. Passing arbitrary strings, including CRLF sequences, as
418+
the `link` value is an application-level misuse of the API, not a Node.js
419+
vulnerability. Node.js validates the structure of Early Hints per the HTTP spec
420+
but does not sanitize free-form application data passed to it; that is the
421+
application's responsibility.
422+
365423
## Assessing experimental features reports
366424

367425
Experimental features are eligible for security reports just like any other

benchmark/buffers/buffer-transcode.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const encodings = ['latin1', 'ascii', 'ucs2', 'utf8'];
88

99
if (!hasIntl) {
1010
console.log('Skipping: `transcode` is only available on platforms that support i18n`');
11-
process.exit(0);
11+
return;
1212
}
1313

1414
const bench = common.createBenchmark(main, {

benchmark/fixtures/transform-types-benchmark.js

Lines changed: 0 additions & 28 deletions
This file was deleted.

benchmark/fixtures/transform-types-benchmark.ts

Lines changed: 0 additions & 30 deletions
This file was deleted.

benchmark/ts/transform-typescript.js

Lines changed: 0 additions & 26 deletions
This file was deleted.

deps/ada/ada.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* auto-generated on 2026-01-30 13:29:04 -0500. Do not edit! */
1+
/* auto-generated on 2026-02-23 21:29:24 -0500. Do not edit! */
22
/* begin file src/ada.cpp */
33
#include "ada.h"
44
/* begin file src/checkers.cpp */
@@ -14495,6 +14495,12 @@ bool url_aggregator::set_pathname(const std::string_view input) {
1449514495
if (get_pathname().starts_with("//") && !has_authority() && !has_dash_dot()) {
1449614496
buffer.insert(components.pathname_start, "/.");
1449714497
components.pathname_start += 2;
14498+
if (components.search_start != url_components::omitted) {
14499+
components.search_start += 2;
14500+
}
14501+
if (components.hash_start != url_components::omitted) {
14502+
components.hash_start += 2;
14503+
}
1449814504
}
1449914505
ADA_ASSERT_TRUE(validate());
1450014506
return true;

deps/ada/ada.h

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* auto-generated on 2026-01-30 13:29:04 -0500. Do not edit! */
1+
/* auto-generated on 2026-02-23 21:29:24 -0500. Do not edit! */
22
/* begin file include/ada.h */
33
/**
44
* @file ada.h
@@ -8091,6 +8091,12 @@ inline void url_aggregator::update_base_pathname(const std::string_view input) {
80918091
// output.
80928092
buffer.insert(components.pathname_start, "/.");
80938093
components.pathname_start += 2;
8094+
if (components.search_start != url_components::omitted) {
8095+
components.search_start += 2;
8096+
}
8097+
if (components.hash_start != url_components::omitted) {
8098+
components.hash_start += 2;
8099+
}
80948100
}
80958101

80968102
uint32_t difference = replace_and_resize(
@@ -9530,13 +9536,14 @@ url_pattern_component<regex_provider>::create_component_match_result(
95309536
auto result =
95319537
url_pattern_component_result{.input = std::move(input), .groups = {}};
95329538

9533-
// Optimization: Let's reserve the size.
9534-
result.groups.reserve(exec_result.size());
9535-
95369539
// We explicitly start iterating from 0 even though the spec
95379540
// says we should start from 1. This case is handled by the
9538-
// std_regex_provider.
9539-
for (size_t index = 0; index < exec_result.size(); index++) {
9541+
// std_regex_provider which removes the full match from index 0.
9542+
// Use min() to guard against potential mismatches between
9543+
// exec_result size and group_name_list size.
9544+
const size_t size = std::min(exec_result.size(), group_name_list.size());
9545+
result.groups.reserve(size);
9546+
for (size_t index = 0; index < size; index++) {
95409547
result.groups.emplace(group_name_list[index],
95419548
std::move(exec_result[index]));
95429549
}
@@ -11221,14 +11228,14 @@ constructor_string_parser<regex_provider>::parse(std::string_view input) {
1122111228
#ifndef ADA_ADA_VERSION_H
1122211229
#define ADA_ADA_VERSION_H
1122311230

11224-
#define ADA_VERSION "3.4.2"
11231+
#define ADA_VERSION "3.4.3"
1122511232

1122611233
namespace ada {
1122711234

1122811235
enum {
1122911236
ADA_VERSION_MAJOR = 3,
1123011237
ADA_VERSION_MINOR = 4,
11231-
ADA_VERSION_REVISION = 2,
11238+
ADA_VERSION_REVISION = 3,
1123211239
};
1123311240

1123411241
} // namespace ada

0 commit comments

Comments
 (0)