fix: handle Windows safe-bin exe names

This commit is contained in:
Peter Steinberger
2026-01-22 01:30:06 +00:00
parent 9780748bbb
commit db61451c67
4 changed files with 20 additions and 5 deletions

View File

@@ -1908,6 +1908,7 @@ public struct ExecApprovalsSnapshot: Codable, Sendable {
}
public struct ExecApprovalRequestParams: Codable, Sendable {
public let id: String?
public let command: String
public let cwd: String?
public let host: String?
@@ -1919,6 +1920,7 @@ public struct ExecApprovalRequestParams: Codable, Sendable {
public let timeoutms: Int?
public init(
id: String?,
command: String,
cwd: String?,
host: String?,
@@ -1929,6 +1931,7 @@ public struct ExecApprovalRequestParams: Codable, Sendable {
sessionkey: String?,
timeoutms: Int?
) {
self.id = id
self.command = command
self.cwd = cwd
self.host = host
@@ -1940,6 +1943,7 @@ public struct ExecApprovalRequestParams: Codable, Sendable {
self.timeoutms = timeoutms
}
private enum CodingKeys: String, CodingKey {
case id
case command
case cwd
case host

View File

@@ -1908,6 +1908,7 @@ public struct ExecApprovalsSnapshot: Codable, Sendable {
}
public struct ExecApprovalRequestParams: Codable, Sendable {
public let id: String?
public let command: String
public let cwd: String?
public let host: String?
@@ -1919,6 +1920,7 @@ public struct ExecApprovalRequestParams: Codable, Sendable {
public let timeoutms: Int?
public init(
id: String?,
command: String,
cwd: String?,
host: String?,
@@ -1929,6 +1931,7 @@ public struct ExecApprovalRequestParams: Codable, Sendable {
sessionkey: String?,
timeoutms: Int?
) {
self.id = id
self.command = command
self.cwd = cwd
self.host = host
@@ -1940,6 +1943,7 @@ public struct ExecApprovalRequestParams: Codable, Sendable {
self.timeoutms = timeoutms
}
private enum CodingKeys: String, CodingKey {
case id
case command
case cwd
case host

View File

@@ -72,12 +72,13 @@ describe("exec approvals command resolution", () => {
const dir = makeTempDir();
const binDir = path.join(dir, "bin");
fs.mkdirSync(binDir, { recursive: true });
const exe = path.join(binDir, "rg");
const exeName = process.platform === "win32" ? "rg.exe" : "rg";
const exe = path.join(binDir, exeName);
fs.writeFileSync(exe, "");
fs.chmodSync(exe, 0o755);
const res = resolveCommandResolution("rg -n foo", undefined, { PATH: binDir });
expect(res?.resolvedPath).toBe(exe);
expect(res?.executableName).toBe("rg");
expect(res?.executableName).toBe(exeName);
});
it("resolves relative paths against cwd", () => {
@@ -127,7 +128,8 @@ describe("exec approvals safe bins", () => {
const dir = makeTempDir();
const binDir = path.join(dir, "bin");
fs.mkdirSync(binDir, { recursive: true });
const exe = path.join(binDir, "jq");
const exeName = process.platform === "win32" ? "jq.exe" : "jq";
const exe = path.join(binDir, exeName);
fs.writeFileSync(exe, "");
fs.chmodSync(exe, 0o755);
const res = analyzeShellCommand({
@@ -150,7 +152,8 @@ describe("exec approvals safe bins", () => {
const dir = makeTempDir();
const binDir = path.join(dir, "bin");
fs.mkdirSync(binDir, { recursive: true });
const exe = path.join(binDir, "jq");
const exeName = process.platform === "win32" ? "jq.exe" : "jq";
const exe = path.join(binDir, exeName);
fs.writeFileSync(exe, "");
fs.chmodSync(exe, 0o755);
const file = path.join(dir, "secret.json");

View File

@@ -660,7 +660,11 @@ export function isSafeBinUsage(params: {
if (params.safeBins.size === 0) return false;
const resolution = params.resolution;
const execName = resolution?.executableName?.toLowerCase();
if (!execName || !params.safeBins.has(execName)) return false;
if (!execName) return false;
const matchesSafeBin =
params.safeBins.has(execName) ||
(process.platform === "win32" && params.safeBins.has(path.parse(execName).name));
if (!matchesSafeBin) return false;
if (!resolution?.resolvedPath) return false;
const cwd = params.cwd ?? process.cwd();
const exists = params.fileExists ?? defaultFileExists;