Merge b831c7bce7411ce65f8a8bdbd0be712d56c69ecd into 598f1826d8b2bc969aace2c6459824737667218c

This commit is contained in:
Rohin 2026-03-20 22:17:17 -05:00 committed by GitHub
commit 9d25c98210
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 35 additions and 7 deletions

View File

@ -51,28 +51,39 @@ describe("getShellConfig", () => {
it("prefers bash when fish is default and bash is on PATH", () => {
const binDir = createTempCommandDir(tempDirs, [{ name: "bash" }]);
process.env.PATH = binDir;
const { shell } = getShellConfig();
const { shell, args } = getShellConfig();
expect(shell).toBe(path.join(binDir, "bash"));
expect(args).toEqual(["--noprofile", "--norc", "-c"]);
});
it("falls back to sh when fish is default and bash is missing", () => {
const binDir = createTempCommandDir(tempDirs, [{ name: "sh" }]);
process.env.PATH = binDir;
const { shell } = getShellConfig();
const { shell, args } = getShellConfig();
expect(shell).toBe(path.join(binDir, "sh"));
expect(args).toEqual(["-c"]);
});
it("falls back to env shell when fish is default and no sh is available", () => {
process.env.PATH = "";
const { shell } = getShellConfig();
const { shell, args } = getShellConfig();
expect(shell).toBe("/usr/bin/fish");
expect(args).toEqual(["--no-config", "-c"]);
});
it("uses zsh no-rc mode to avoid startup-file env overrides", () => {
process.env.SHELL = "/bin/zsh";
const { shell, args } = getShellConfig();
expect(shell).toBe("/bin/zsh");
expect(args).toEqual(["-f", "-c"]);
});
it("uses sh when SHELL is unset", () => {
delete process.env.SHELL;
process.env.PATH = "";
const { shell } = getShellConfig();
const { shell, args } = getShellConfig();
expect(shell).toBe("sh");
expect(args).toEqual(["-c"]);
});
});

View File

@ -39,6 +39,23 @@ export function resolvePowerShellPath(): string {
return "powershell.exe";
}
function resolvePosixShellArgs(shellPath: string): string[] {
const shellName = normalizeShellName(shellPath);
// Keep exec commands deterministic: avoid user startup files overriding inherited
// daemon environment variables (for example launchd-provided secrets on macOS).
if (shellName === "zsh") {
return ["-f", "-c"];
}
if (shellName === "bash") {
return ["--noprofile", "--norc", "-c"];
}
if (shellName === "fish") {
return ["--no-config", "-c"];
}
return ["-c"];
}
export function getShellConfig(): { shell: string; args: string[] } {
if (process.platform === "win32") {
// Use PowerShell instead of cmd.exe on Windows.
@ -58,15 +75,15 @@ export function getShellConfig(): { shell: string; args: string[] } {
if (shellName === "fish") {
const bash = resolveShellFromPath("bash");
if (bash) {
return { shell: bash, args: ["-c"] };
return { shell: bash, args: resolvePosixShellArgs(bash) };
}
const sh = resolveShellFromPath("sh");
if (sh) {
return { shell: sh, args: ["-c"] };
return { shell: sh, args: resolvePosixShellArgs(sh) };
}
}
const shell = envShell && envShell.length > 0 ? envShell : "sh";
return { shell, args: ["-c"] };
return { shell, args: resolvePosixShellArgs(shell) };
}
export function resolveShellFromPath(name: string): string | undefined {