Skip to content

Conversation

@santigimeno
Copy link
Member

@santigimeno santigimeno commented Aug 12, 2025

To allow us to read the Build-Id from ELF headers in a specific binary.

Summary by CodeRabbit

  • Chores

    • Updated Linux build configuration to include ELF utilities and link required libraries, with no impact on other platforms.
    • Refined linker behavior on Linux and OpenHarmony to improve compatibility.
  • Tests

    • Added a Linux-only integration test that validates build ID retrieval via a native addon.
    • Introduced a supporting test addon to exercise the new Linux functionality.

@coderabbitai
Copy link

coderabbitai bot commented Aug 12, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

Adds Linux-only ELF build-id utilities (source and header), updates build configs to include them and adjust Linux/OpenHarmony linker flags, and introduces a Linux-specific test addon and test script that validates build-id retrieval from the Node executable using libelf.

Changes

Cohort / File(s) Summary
Build configuration (Linux/OpenHarmony linking)
node.gypi
Split Linux and OpenHarmony linker rules. Linux now links -lelf and conditionally -lrt based on nsolid_use_librt; OpenHarmony continues excluding -lrt.
nsolid Linux sources inclusion
node.gyp
Adds Linux-specific sources to nsolid_sources: src/nsolid/nsolid_elf_utils.cc, src/nsolid/nsolid_elf_utils.h.
ELF build-id utility (implementation and API)
src/nsolid/nsolid_elf_utils.cc, src/nsolid/nsolid_elf_utils.h
Introduces node::nsolid::elf_utils::GetBuildId(path, build_id) with in-process caching; parses .note.gnu.build-id via libelf and returns hex build-id or error. Header gated by NODE_WANT_INTERNALS.
Test addon and test script (Linux-only)
test/addons/nsolid-elf-utils/binding.cc, test/addons/nsolid-elf-utils/binding.gyp, test/addons/nsolid-elf-utils/nsolid-elf-utils.js
Adds addon exposing getBuildId(path) and a test comparing its output to readelf -n on process.execPath. Build defines NODE_WANT_INTERNALS=1.

Sequence Diagram(s)

sequenceDiagram
  participant TestJS as Test (nsolid-elf-utils.js)
  participant Addon as Native Addon (binding.cc)
  participant Utils as elf_utils::GetBuildId
  participant LibELF as libelf
  TestJS->>Addon: getBuildId(process.execPath)
  Addon->>Utils: GetBuildId(path, &build_id)
  Utils->>LibELF: elf_version/elf_begin/iterate sections
  LibELF-->>Utils: .note.gnu.build-id data
  Utils-->>Addon: build_id (hex) or error
  Addon-->>TestJS: build_id string (on success)
  TestJS->>TestJS: assert equals readelf-derived ID
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

I nosed through notes in ELF-lit night,
Found a build-id shining bright.
With lil’ paws tapping C++ keys,
I cached the string with whiskered ease.
Tests hopped green—what a sight!
Carrot commits? Approved outright. 🥕✨


Comment @coderabbitai help to get the list of available commands and usage tips.

@santigimeno santigimeno self-assigned this Aug 12, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
src/nsolid/nsolid_elf_utils.h (1)

12-12: Consider documenting the return value semantics.

The function returns an int status code, but the expected values (0 for success, non-zero for failure) should be documented for API clarity.

Add a brief comment documenting the return value:

 namespace elf_utils {
+  // Returns 0 on success, non-zero on failure.
   int GetBuildId(const std::string& path, std::string* build_id);
 }  // namespace elf_utils
test/addons/nsolid-elf-utils/binding.cc (1)

14-29: Consider returning an error instead of undefined when GetBuildId fails.

When GetBuildId returns a non-zero error code, the function currently returns undefined by not setting any return value. This makes it difficult for JavaScript code to distinguish between different error conditions (file not found, invalid ELF, no build-id, etc.).

Consider throwing a JavaScript exception with the error code to provide better error context:

 static void GetBuildId(const FunctionCallbackInfo<Value>& args) {
 #if defined(__linux__)
   Isolate* isolate = args.GetIsolate();
   assert(args[0]->IsString());
   v8::String::Utf8Value path_utf8(isolate, args[0]);
   std::string path(*path_utf8, path_utf8.length());
   std::string build_id;
   int res = node::nsolid::elf_utils::GetBuildId(path, &build_id);
   if (res != 0) {
-    return;
+    std::string error_msg = "Failed to get build-id: error code " + std::to_string(res);
+    isolate->ThrowException(v8::Exception::Error(
+        String::NewFromUtf8(isolate, error_msg.c_str()).ToLocalChecked()));
+    return;
   }
 
   args.GetReturnValue().Set(
     String::NewFromUtf8(isolate, build_id.c_str()).ToLocalChecked());
 #endif
 }
src/nsolid/nsolid_elf_utils.cc (1)

29-35: Consider returning more specific error codes.

The function returns elf_errno() when elf_version(EV_CURRENT) fails. While this is technically correct, elf_errno() might return 0 if no error was previously set, which could be confusing.

Consider returning a more specific error code or ensuring elf_errno() is non-zero:

   ret = 0;
   if (elf_version(EV_CURRENT) == EV_NONE) {
-    return elf_errno();
+    int err = elf_errno();
+    return err ? err : ELF_E_VERSION;
   }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cd19746 and a6d9f60.

📒 Files selected for processing (7)
  • node.gyp (1 hunks)
  • node.gypi (1 hunks)
  • src/nsolid/nsolid_elf_utils.cc (1 hunks)
  • src/nsolid/nsolid_elf_utils.h (1 hunks)
  • test/addons/nsolid-elf-utils/binding.cc (1 hunks)
  • test/addons/nsolid-elf-utils/binding.gyp (1 hunks)
  • test/addons/nsolid-elf-utils/nsolid-elf-utils.js (1 hunks)
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: santigimeno
PR: nodesource/nsolid#339
File: src/nsolid/nsolid_elf_utils.cc:18-18
Timestamp: 2025-07-08T16:05:45.341Z
Learning: In the NSolid project, the `GetBuildId` function in `src/nsolid/nsolid_elf_utils.cc` is designed to be called only from the NSolid thread, so the static cache doesn't require thread safety mechanisms like mutex protection.
📚 Learning: 2025-07-08T16:05:45.341Z
Learnt from: santigimeno
PR: nodesource/nsolid#339
File: src/nsolid/nsolid_elf_utils.cc:18-18
Timestamp: 2025-07-08T16:05:45.341Z
Learning: In the NSolid project, the `GetBuildId` function in `src/nsolid/nsolid_elf_utils.cc` is designed to be called only from the NSolid thread, so the static cache doesn't require thread safety mechanisms like mutex protection.

Applied to files:

  • src/nsolid/nsolid_elf_utils.h
  • test/addons/nsolid-elf-utils/nsolid-elf-utils.js
  • src/nsolid/nsolid_elf_utils.cc
  • test/addons/nsolid-elf-utils/binding.cc
📚 Learning: 2025-07-08T14:48:04.827Z
Learnt from: santigimeno
PR: nodesource/nsolid#339
File: test/addons/nsolid-elf-utils/binding.cc:13-28
Timestamp: 2025-07-08T14:48:04.827Z
Learning: In nsolid test native addons (e.g., `test/addons/*/binding.cc`), additional JavaScript-facing argument validation is typically omitted because the tests supply well-formed inputs.

Applied to files:

  • test/addons/nsolid-elf-utils/binding.gyp
  • test/addons/nsolid-elf-utils/nsolid-elf-utils.js
  • test/addons/nsolid-elf-utils/binding.cc
📚 Learning: 2025-07-08T14:46:47.806Z
Learnt from: santigimeno
PR: nodesource/nsolid#339
File: test/addons/nsolid-elf-utils/nsolid-elf-utils.js:13-14
Timestamp: 2025-07-08T14:46:47.806Z
Learning: In the nsolid test suite, native addon bindings are expected to be built beforehand; tests do not add fs.existsSync guards to skip when bindings are missing.

Applied to files:

  • test/addons/nsolid-elf-utils/binding.gyp
  • test/addons/nsolid-elf-utils/nsolid-elf-utils.js
  • test/addons/nsolid-elf-utils/binding.cc
📚 Learning: 2025-07-08T14:47:34.724Z
Learnt from: santigimeno
PR: nodesource/nsolid#339
File: test/addons/nsolid-elf-utils/nsolid-elf-utils.js:16-18
Timestamp: 2025-07-08T14:47:34.724Z
Learning: In the nsolid test suite, external tool invocations (e.g., execSync to run `readelf`) are intentionally left uncaught so that any failure causes the test to fail rather than being skipped.

Applied to files:

  • test/addons/nsolid-elf-utils/nsolid-elf-utils.js
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: build-tarball
  • GitHub Check: lint-js-and-md
  • GitHub Check: coverage-windows
  • GitHub Check: test-macOS
  • GitHub Check: build-docs
  • GitHub Check: test-linux (ubuntu-24.04-arm)
  • GitHub Check: test-linux (ubuntu-24.04)
🔇 Additional comments (13)
node.gypi (1)

553-565: LGTM! Cleaner separation of linker rules for OpenHarmony and Linux.

The refactoring properly splits the combined condition into two OS-specific blocks, making the linker configuration more maintainable and explicit for each platform. The Linux block now unconditionally links -lelf (required for the new ELF utilities) and conditionally handles -lrt based on nsolid_use_librt.

test/addons/nsolid-elf-utils/binding.gyp (1)

1-10: LGTM! Properly configured test addon target.

The binding target is correctly configured with the necessary NODE_WANT_INTERNALS=1 define to access the internal ELF utilities API, and properly includes the common build settings.

node.gyp (1)

581-586: LGTM! Correct Linux-specific inclusion of ELF utilities.

The conditional addition of ELF utility sources to nsolid_sources on Linux is properly implemented, aligning with the platform-specific nature of the Build-Id functionality.

test/addons/nsolid-elf-utils/nsolid-elf-utils.js (4)

1-11: LGTM! Proper platform check and early exit.

The platform check correctly skips the test on non-Linux systems with an informative message.


13-14: LGTM! Consistent with nsolid test suite conventions.

The binding loading follows the established pattern without fs.existsSync guards, as per the team's conventions documented in the learnings.


20-23: LGTM! Clear test assertion with helpful error message.

The test correctly validates the Build ID and provides a descriptive error message on mismatch, which aids in debugging.


16-18: Add a clear fallback when readelf is missing

To prevent cryptic ENOENT failures in CI environments where readelf isn’t installed, wrap the execSync invocation in a try/catch and emit a descriptive error (or provide alternate logic) if readelf isn’t found:

• File: test/addons/nsolid-elf-utils/nsolid-elf-utils.js
• Lines: 16–18

Suggested update:

let expected;
try {
  expected = execSync(
    `readelf -n ${process.execPath} | awk '/Build ID/ { print $3 }'`,
    { encoding: 'utf8' }
  ).trim();
} catch (err) {
  if (err.code === 'ENOENT') {
    throw new Error(
      'The `readelf` tool is required to run this test but was not found in your PATH.'
    );
  }
  throw err;
}

This ensures that missing dependencies produce a clear, actionable error.

⛔ Skipped due to learnings
Learnt from: santigimeno
PR: nodesource/nsolid#339
File: test/addons/nsolid-elf-utils/nsolid-elf-utils.js:16-18
Timestamp: 2025-07-08T14:47:34.724Z
Learning: In the nsolid test suite, external tool invocations (e.g., execSync to run `readelf`) are intentionally left uncaught so that any failure causes the test to fail rather than being skipped.
Learnt from: santigimeno
PR: nodesource/nsolid#339
File: test/addons/nsolid-elf-utils/nsolid-elf-utils.js:13-14
Timestamp: 2025-07-08T14:46:47.806Z
Learning: In the nsolid test suite, native addon bindings are expected to be built beforehand; tests do not add fs.existsSync guards to skip when bindings are missing.
src/nsolid/nsolid_elf_utils.h (1)

1-19: LGTM! Well-structured header with proper guards.

The header is properly organized with:

  • Standard include guards
  • NODE_WANT_INTERNALS conditional compilation
  • Clear namespace hierarchy
  • Clean API declaration
test/addons/nsolid-elf-utils/binding.cc (2)

1-7: LGTM!

The header includes and platform-specific guard are properly structured.


31-33: LGTM!

Module initialization correctly exports the function.

src/nsolid/nsolid_elf_utils.cc (3)

1-15: LGTM!

Headers are properly included and namespaces are correctly structured.


17-28: Thread safety consideration for the static cache.

Based on the retrieved learnings, the GetBuildId function is designed to be called only from the NSolid thread, so the static cache doesn't require thread safety mechanisms. This design constraint is valid for the current implementation.


85-90: Resource cleanup order looks correct.

The cleanup sequence properly handles both the ELF object and file descriptor in the correct order, ensuring resources are freed even on error paths.

Comment on lines 53 to 77
*build_id = std::string("");
while ((scn = elf_nextscn(e, scn)) != nullptr) {
if (gelf_getshdr(scn, &shdr) != &shdr) {
ret = elf_errno();
goto end_error;
}

char* name = elf_strptr(e, shstrndx, shdr.sh_name);
if (name && strcmp(name, ".note.gnu.build-id") == 0) {
Elf_Data* data = elf_getdata(scn, nullptr);
if (data && data->d_size >= 16) {
// ELF Note header: namesz(4), descsz(4), type(4) + name padding
// Compute offset to build-id properly
uint32_t* note = reinterpret_cast<uint32_t*>(data->d_buf);
uint32_t namesz = note[0];
uint32_t descsz = note[1];
// Name starts at offset 12
// Descriptor (build-id) starts at next aligned offset
size_t name_end = 12 + ((namesz + 3) & ~3);
uint8_t* id = reinterpret_cast<uint8_t*>(data->d_buf) + name_end;
*build_id = utils::buffer_to_hex(id, descsz);
break;
}
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Potential buffer overflow risk in ELF note parsing.

The code assumes the ELF note structure without validating that the computed offsets don't exceed the buffer bounds. While data->d_size >= 16 checks for minimum size, it doesn't ensure that name_end + descsz doesn't exceed data->d_size.

Add bounds checking before accessing the build-id data:

   *build_id = std::string("");
   while ((scn = elf_nextscn(e, scn)) != nullptr) {
     if (gelf_getshdr(scn, &shdr) != &shdr) {
       ret = elf_errno();
       goto end_error;
     }
 
     char* name = elf_strptr(e, shstrndx, shdr.sh_name);
     if (name && strcmp(name, ".note.gnu.build-id") == 0) {
       Elf_Data* data = elf_getdata(scn, nullptr);
       if (data && data->d_size >= 16) {
         // ELF Note header: namesz(4), descsz(4), type(4) + name padding
         // Compute offset to build-id properly
         uint32_t* note = reinterpret_cast<uint32_t*>(data->d_buf);
         uint32_t namesz = note[0];
         uint32_t descsz = note[1];
         // Name starts at offset 12
         // Descriptor (build-id) starts at next aligned offset
         size_t name_end = 12 + ((namesz + 3) & ~3);
+        // Ensure we don't read beyond the buffer
+        if (name_end + descsz > data->d_size) {
+          ret = ELF_E_DATA;
+          goto end_error;
+        }
         uint8_t* id = reinterpret_cast<uint8_t*>(data->d_buf) + name_end;
         *build_id = utils::buffer_to_hex(id, descsz);
         break;
       }
     }
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
*build_id = std::string("");
while ((scn = elf_nextscn(e, scn)) != nullptr) {
if (gelf_getshdr(scn, &shdr) != &shdr) {
ret = elf_errno();
goto end_error;
}
char* name = elf_strptr(e, shstrndx, shdr.sh_name);
if (name && strcmp(name, ".note.gnu.build-id") == 0) {
Elf_Data* data = elf_getdata(scn, nullptr);
if (data && data->d_size >= 16) {
// ELF Note header: namesz(4), descsz(4), type(4) + name padding
// Compute offset to build-id properly
uint32_t* note = reinterpret_cast<uint32_t*>(data->d_buf);
uint32_t namesz = note[0];
uint32_t descsz = note[1];
// Name starts at offset 12
// Descriptor (build-id) starts at next aligned offset
size_t name_end = 12 + ((namesz + 3) & ~3);
uint8_t* id = reinterpret_cast<uint8_t*>(data->d_buf) + name_end;
*build_id = utils::buffer_to_hex(id, descsz);
break;
}
}
}
*build_id = std::string("");
while ((scn = elf_nextscn(e, scn)) != nullptr) {
if (gelf_getshdr(scn, &shdr) != &shdr) {
ret = elf_errno();
goto end_error;
}
char* name = elf_strptr(e, shstrndx, shdr.sh_name);
if (name && strcmp(name, ".note.gnu.build-id") == 0) {
Elf_Data* data = elf_getdata(scn, nullptr);
if (data && data->d_size >= 16) {
// ELF Note header: namesz(4), descsz(4), type(4) + name padding
// Compute offset to build-id properly
uint32_t* note = reinterpret_cast<uint32_t*>(data->d_buf);
uint32_t namesz = note[0];
uint32_t descsz = note[1];
// Name starts at offset 12
// Descriptor (build-id) starts at next aligned offset
size_t name_end = 12 + ((namesz + 3) & ~3);
// Ensure we don't read beyond the buffer
if (name_end + descsz > data->d_size) {
ret = ELF_E_DATA;
goto end_error;
}
uint8_t* id = reinterpret_cast<uint8_t*>(data->d_buf) + name_end;
*build_id = utils::buffer_to_hex(id, descsz);
break;
}
}
}
🤖 Prompt for AI Agents
In src/nsolid/nsolid_elf_utils.cc around lines 53 to 77, the ELF note parsing
computes name_end and then reads descsz bytes without verifying the computed
offsets fit inside data->d_size; add explicit bounds checks before accessing the
build-id: validate data and data->d_buf are non-null, cast namesz and descsz to
size_t and check namesz/descsz are reasonable (e.g. not absurdly large), compute
name_end = 12 + ((namesz + 3) & ~3) using size_t and ensure name_end <=
data->d_size and name_end + descsz <= data->d_size (also guard against overflow
when adding), and only then set *build_id from the id pointer; on failure, skip
this note or set an error/continue instead of reading out-of-bounds.

@santigimeno santigimeno changed the base branch from node-v22.x-nsolid-v5.x to node-v22.x-nsolid-v6.x September 23, 2025 08:54
gurgunday and others added 26 commits November 7, 2025 18:11
PR-URL: nodejs/node#60120
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Gerhard Stöbich <deb2001-github@yahoo.de>
Add file attribute normalization in JUnit test output transform to
support upcoming file attribute feature in JUnit XML reporter.

PR-URL: nodejs/node#59432
Fixes: nodejs/node#59422
Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
Reviewed-By: Pietro Marchini <pietro.marchini94@gmail.com>
Add file attribute to JUnit testcase elements when file information
is available in test event data.

PR-URL: nodejs/node#59432
Fixes: nodejs/node#59422
Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
Reviewed-By: Pietro Marchini <pietro.marchini94@gmail.com>
PR-URL: nodejs/node#60134
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Ulises Gascón <ulisesgascongonzalez@gmail.com>
PR-URL: nodejs/node#60135
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Tim Perry <pimterry@gmail.com>
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
PR-URL: nodejs/node#59853
Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
Add a delay before writing the files to ensure that the watcher receives
the notifications.

Fixes: nodejs/node#60051
Refs: nodejs/node#52601
PR-URL: nodejs/node#60060
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
PR-URL: nodejs/node#60144
Reviewed-By: Richard Lau <richard.lau@ibm.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Ulises Gascón <ulisesgascongonzalez@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
PR-URL: nodejs/node#60148
Reviewed-By: Richard Lau <richard.lau@ibm.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Corrects the misspelling of "privateSynbol" to "privateSymbol".

PR-URL: nodejs/node#60155
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Richard Lau <richard.lau@ibm.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
PR-URL: nodejs/node#59890
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
PR-URL: nodejs/node#60163
Reviewed-By: Daeyeon Jeong <daeyeon.dev@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: nodejs/node#60173
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Reviewed-By: Vinícius Lourenço Claro Cardoso <contact@viniciusl.com.br>
Reviewed-By: Richard Lau <richard.lau@ibm.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
PR-URL: nodejs/node#60065
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
...and other minor cleanups

PR-URL: nodejs/node#60061
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
* Track memory held by the Lock instance
* Clean up some Utf8/TwoByteString handling

PR-URL: nodejs/node#60061
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
PR-URL: nodejs/node#60179
Reviewed-By: Richard Lau <richard.lau@ibm.com>
Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: nodejs/node#60168
Reviewed-By: Jordan Harband <ljharb@gmail.com>
Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
Reviewed-By: Ulises Gascón <ulisesgascongonzalez@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
PR-URL: nodejs/node#60182
Refs: https://discord.com/channels/425824580918181889/425824580918181891/1425966053242048584
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
PR-URL: nodejs/node#60209
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
This reverts commit 9790315e158a0560932595ff9df9c598e1c2c285.

Refs: nodejs/node#59952
PR-URL: nodejs/node#60126
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
PR-URL: nodejs/node#60208
Reviewed-By: Richard Lau <richard.lau@ibm.com>
Reviewed-By: Daeyeon Jeong <daeyeon.dev@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Darshan Sen <raisinten@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Tim Perry <pimterry@gmail.com>
Fixes the constructor name in the stack tree for _errnoException.

PR-URL: nodejs/node#60156
Reviewed-By: Daeyeon Jeong <daeyeon.dev@gmail.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
PR-URL: nodejs/node#60062
Fixes: nodejs/node#60025
Reviewed-By: Tim Perry <pimterry@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
PR-URL: nodejs/node#60219
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Reviewed-By: Chemi Atlow <chemi@atlow.co.il>
PR-URL: nodejs/node#60224
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Ulises Gascón <ulisesgascongonzalez@gmail.com>
santigimeno and others added 28 commits December 9, 2025 11:30
PR-URL: #388
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
PR-URL: #389
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
PR-URL: #390
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Notable changes:

http:
  * (SEMVER-MINOR) add optimizeEmptyRequests server option (Rafael Gonzaga) nodejs/node#59778
lib:
  * (SEMVER-MINOR) add options to util.deprecate (Rafael Gonzaga) nodejs/node#59982
module:
  * (SEMVER-MINOR) mark type stripping as stable (Marco Ippolito) nodejs/node#60600
node-api:
  * (SEMVER-MINOR) add napi_create_object_with_properties (Miguel Marcondes Filho) nodejs/node#59953
sqlite:
  * (SEMVER-MINOR) allow setting defensive flag (Bart Louwers) nodejs/node#60217
src:
  * (SEMVER-MINOR) add watch config namespace (Marco Ippolito) nodejs/node#60178
  * (SEMVER-MINOR) add an option to make compile cache portable (Aditi) nodejs/node#58797
src,permission:
  * (SEMVER-MINOR) add --allow-inspector ability (Rafael Gonzaga) nodejs/node#59711
v8:
  * (SEMVER-MINOR) add cpu profile (theanarkh) nodejs/node#59807

PR-URL: nodejs/node#61001
PR-URL: #398
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Fixes: #197
PR-URL: #401
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Refs: https://hackerone.com/reports/3390084
PR-URL: nodejs-private/node-private#748
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
CVE-ID: CVE-2025-55132
Only grpc insecure connections were being used in the tests. Also, these
new tests allow to cover for the untested `NSOLID_GRPC_CERTS` env
variable.

PR-URL: #406
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
By setting the `NSOLID_GRPC_KEYLOG` to a truthy value, a new keylog file
will be generated that should allow us to decrypt the TLS v1.3
connections gRPC Agent uses. Very useful to debug issues on production.
The file will be generated in the current working directory with the
following format: `nsolid-tls-keylog-<process_pid>.log`.

PR-URL: #406
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Refs: https://hackerone.com/reports/3417819
Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com>
PR-URL: nodejs-private/node-private#760
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
CVE-ID: CVE-2025-55130
When a stack overflow exception occurs during async_hooks callbacks
(which use TryCatchScope::kFatal), detect the specific "Maximum call
stack size exceeded" RangeError and re-throw it instead of immediately
calling FatalException. This allows user code to catch the exception
with try-catch blocks instead of requiring uncaughtException handlers.

The implementation adds IsStackOverflowError() helper to detect stack
overflow RangeErrors and re-throws them in TryCatchScope destructor
instead of calling FatalException.

This fixes the issue where async_hooks would cause stack overflow
exceptions to exit with code 7 (kExceptionInFatalExceptionHandler)
instead of being catchable.

Fixes: nodejs/node#37989
Ref: https://hackerone.com/reports/3456295
PR-URL: nodejs-private/node-private#773
Refs: https://hackerone.com/reports/3456295
Reviewed-By: Robert Nagy <ronagy@icloud.com>
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
CVE-ID: CVE-2025-59466
Wrap pskCallback and ALPNCallback invocations in try-catch blocks
to route exceptions through owner.destroy() instead of letting them
become uncaught exceptions. This prevents remote attackers from
crashing TLS servers or causing resource exhaustion.

Fixes: https://hackerone.com/reports/3473882
PR-URL: nodejs-private/node-private#796
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
CVE-ID: CVE-2026-21637
This prevents the server from crashing due to an unhandled rejection
when a TLSSocket connection is abruptly destroyed during initialization
and the user has not attached an error handler to the socket.
e.g:

```js
const server = http2.createSecureServer({ ... })
server.on('secureConnection', socket => {
  socket.on('error', err => {
    console.log(err)
  })
})
```

PR-URL: nodejs-private/node-private#797
Fixes: nodejs/node#44751
Refs: https://hackerone.com/bugs?subject=nodejs&report_id=3262404
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
CVE-ID: CVE-2025-59465
PR-URL: nodejs/node#61283
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Richard Lau <richard.lau@ibm.com>
Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
Reviewed-By: Aviv Keller <me@aviv.sh>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Reviewed-By: Matthew Aitken <maitken033380023@gmail.com>
PR-URL: nodejs/node#60997
Reviewed-By: Richard Lau <richard.lau@ibm.com>
Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Juan José Arboleda <soyjuanarbol@gmail.com>
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Ethan Arrowood <ethan@arrowood.dev>
This removes the zero-fill toggle mechanism that allowed JavaScript
to control ArrayBuffer initialization via shared memory. Instead,
unsafe buffer creation now uses a dedicated C++ API.

Refs: https://hackerone.com/reports/3405778
Co-Authored-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com>
PR-URL: nodejs-private/node-private#759
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
CVE-ID: CVE-2025-55131
This is a security release.

Notable changes:

lib:
  * (CVE-2025-59465) add TLSSocket default error handler (RafaelGSS) <nodejs-private/node-private#797>
  * (CVE-2025-55132) disable futimes when permission model is enabled (RafaelGSS) <nodejs-private/node-private#748>
lib,permission:
  * (CVE-2025-55130) require full read and write to symlink APIs (RafaelGSS) <nodejs-private/node-private#760>
src:
  * (CVE-2025-59466) rethrow stack overflow exceptions in async\_hooks (Matteo Collina) <nodejs-private/node-private#773>
src,lib:
  * (CVE-2025-55131) refactor unsafe buffer creation to remove zero-fill toggle (Сковорода Никита Андреевич) <nodejs-private/node-private#759>
tls:
  * (CVE-2026-21637) route callback exceptions through error handlers (Matteo Collina) <nodejs-private/node-private#796>

PR-URL: nodejs-private/node-private#800
2026-01-13 Node.js v24.13.0 'Krypton' (LTS) Release
Git-EVTag-v0-SHA512: f6fd214d8fef7bb59d5ca9692798b55f4ac592c11fbaf66e18cafb8dbbfb20ed8787324e69843402e11eb0b6a39f584d0497416ff14f2512b2ab3b6778d9b8ef
Don't set `OtlpGrpcClientOptions.use_ssl_credentials` when also setting
`OtlpGrpcClientOptions.credentials`.
Specifically in `EnvInst::CustomCommandReqWeakCallback()` when trying to
access `EnvInst` associated with the `Isolate`. Observed when
load-testing the `test/addons/nsolid-custom-command` test.
To allow us to read the Build-Id from ELF headers in a specific binary.
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.