diff --git a/src/bootstrap/node-extra-ca-certs.test.ts b/src/bootstrap/node-extra-ca-certs.test.ts index 61895b606ca..63d001da07c 100644 --- a/src/bootstrap/node-extra-ca-certs.test.ts +++ b/src/bootstrap/node-extra-ca-certs.test.ts @@ -48,6 +48,63 @@ describe("isNodeVersionManagerRuntime", () => { it("returns false for non-nvm node paths", () => { expect(isNodeVersionManagerRuntime({}, "/usr/bin/node")).toBe(false); }); + + it("detects fnm via execPath", () => { + expect( + isNodeVersionManagerRuntime({}, "/home/test/.fnm/node-versions/v22/installation/bin/node"), + ).toBe(true); + }); + + it("detects fnm via XDG data path", () => { + expect( + isNodeVersionManagerRuntime( + {}, + "/home/test/.local/share/fnm/node-versions/v22/installation/bin/node", + ), + ).toBe(true); + }); + + it("detects nvs via dotted home path", () => { + expect(isNodeVersionManagerRuntime({}, "/home/test/.nvs/node/22.14.0/x64/bin/node")).toBe(true); + }); + + it("detects volta via execPath", () => { + expect( + isNodeVersionManagerRuntime({}, "/home/test/.volta/tools/image/node/22.14.0/bin/node"), + ).toBe(true); + }); + + it("detects asdf via execPath", () => { + expect( + isNodeVersionManagerRuntime({}, "/home/test/.asdf/installs/nodejs/22.14.0/bin/node"), + ).toBe(true); + }); + + it("detects mise via execPath", () => { + expect( + isNodeVersionManagerRuntime({}, "/home/test/.local/share/mise/installs/node/22.14.0/bin/node"), + ).toBe(true); + }); + + it("detects n via execPath", () => { + expect(isNodeVersionManagerRuntime({}, "/home/test/.n/bin/node")).toBe(true); + }); + + it("detects nodenv via execPath", () => { + expect(isNodeVersionManagerRuntime({}, "/home/test/.nodenv/versions/22.14.0/bin/node")).toBe( + true, + ); + }); + + it("detects nodebrew via execPath", () => { + expect(isNodeVersionManagerRuntime({}, "/home/test/.nodebrew/node/v22.14.0/bin/node")).toBe( + true, + ); + }); + + it("detects nvs via execPath", () => { + expect(isNodeVersionManagerRuntime({}, "/home/test/nvs/node/22.14.0/x64/bin/node")).toBe(true); + }); }); describe("resolveAutoNodeExtraCaCerts", () => { diff --git a/src/bootstrap/node-extra-ca-certs.ts b/src/bootstrap/node-extra-ca-certs.ts index e96a7e264ae..06260d00fcd 100644 --- a/src/bootstrap/node-extra-ca-certs.ts +++ b/src/bootstrap/node-extra-ca-certs.ts @@ -32,6 +32,27 @@ export function resolveLinuxSystemCaBundle( return undefined; } +/** + * Version manager path markers (Linux subset), mirroring VERSION_MANAGER_MARKERS + * in src/daemon/runtime-paths.ts. Not imported directly because bootstrap code + * must avoid daemon-layer dependencies at startup. + * Version-manager-installed Node does not inherit system CA certificates, + * so we detect this to auto-inject NODE_EXTRA_CA_CERTS. + */ +const VERSION_MANAGER_PATH_MARKERS: readonly string[] = [ + "/.nvm/", + "/.fnm/", + "/.local/share/fnm/", + "/.volta/", + "/.asdf/", + "/.local/share/mise/", + "/.n/", + "/.nodenv/", + "/.nodebrew/", + "/nvs/", + "/.nvs/", +]; + export function isNodeVersionManagerRuntime( env: EnvMap = process.env as EnvMap, execPath: string = process.execPath, @@ -39,7 +60,7 @@ export function isNodeVersionManagerRuntime( if (env.NVM_DIR?.trim()) { return true; } - return execPath.includes("/.nvm/"); + return VERSION_MANAGER_PATH_MARKERS.some((marker) => execPath.includes(marker)); } export function resolveAutoNodeExtraCaCerts(