🚀 Enhancements
fix(toolchain): repair dangling onedir symlink entrypoints (node) @sgtoj (#2754)
## what- onedir (multi-file) installs now recreate an archive's internal symlink entrypoints using the archive's original relative target (e.g.
../lib/node_modules/corepack/dist/corepack.js) instead of a root-rebased path. - Fixes
nodejs/node, whosecorepack/npm/npxentrypoints are symlinks into a sibling../lib/tree:node@<=24.10.0(whosefiles:list leads withcorepack) no longer fails the install withchmod .../bin/corepack: no such file or directory.node@24.18.0no longer reports success while leavingnpm/npxdangling.- After install,
node,npm,npx, andcorepackall resolve to real files and run.
- Adds a regression test that installs a leading-symlink onedir package under a relative
install_path(the real-world default, e.g.install_path: .tools) and asserts the entrypoint resolves viaos.Stat(follows the link) and ischmod-able — the exact operation that failed. - Updates the symlink-target unit assertions to expect the archive-relative target, and corrects the onedir docs note that claimed targets are "recreated absolute."
why
createValidatedSymlinkForOSwrote the containment-validatedresolvedpath as the symlink target.resolvedis the target rebased onto the toolchain root, so with a relative install root (the default.tools) it became a cwd-relative path. A symlink is interpreted relative to its own directory, so.../bin/corepack -> .tools/bin/.../lib/...resolved to.../bin/.tools/bin/.../lib/...and dangled. This reproduced independently ofinstall_path.- Writing the archive's original relative
linknamereproduces the upstream archive exactly and resolves correctly whether the install root is absolute or relative. resolvedis still used for the security containment check and the Windows copy/hard-link fallback, and absolute targets are still rejected — no change to the archive-symlink "arbitrary file write" protection.- Note: this is a POSIX-only change (macOS/Linux). Windows onedir installs don't create symlinks — an archive's file symlink is reproduced as a hard link/copy via that unchanged
resolved-based fallback, andnodejs/nodeships.cmdshims there — so Windows behavior is unaffected.
references
- Follow-up to #2750 (multi-file / "onedir" installs), which shipped the onedir install path but left
nodejs/node's internal symlink entrypoints dangling. - Testing:
go test ./pkg/toolchain/... ./cmd/toolchain/...passes; the new regression test fails on the pre-fix code with the exactchmod ... corepack: no such file or directoryerror. Also exercised on a GitHub-hostedwindows-latestrunner (pkg/toolchain/installerpackage green; symlink-privilege tests self-skip on Windows, Windows hard-link/copy fallback covered).
Summary by CodeRabbit
-
Bug Fixes
- Fixed onedir installations so archived relative symlinks resolve correctly when using absolute or relative install paths.
- Ensured symlink-based entry points correctly resolve to their target executables.
-
Documentation
- Clarified that archived symlinks retain their relative targets while remaining safely within the installation package.