fix(security): harden safeBins stdin-only enforcement

This commit is contained in:
Peter Steinberger
2026-02-19 14:07:43 +01:00
parent 3c127b6eac
commit cfe8457a0f
6 changed files with 200 additions and 7 deletions

View File

@@ -21,6 +21,7 @@ import {
resolveExecApprovalsFromFile,
resolveExecApprovalsPath,
resolveExecApprovalsSocketPath,
resolveSafeBins,
type ExecAllowlistEntry,
type ExecApprovalsFile,
} from "./exec-approvals.js";
@@ -414,6 +415,9 @@ describe("exec approvals safe bins", () => {
argv: string[];
resolvedPath: string;
expected: boolean;
safeBins?: string[];
executableName?: string;
rawExecutable?: string;
cwd?: string;
setup?: (cwd: string) => void;
};
@@ -439,6 +443,38 @@ describe("exec approvals safe bins", () => {
expected: false,
cwd: "/tmp",
},
{
name: "blocks sort output path via -o <file>",
argv: ["sort", "-o", "malicious.sh"],
resolvedPath: "/usr/bin/sort",
expected: false,
safeBins: ["sort"],
executableName: "sort",
},
{
name: "blocks sort output path via attached short option (-ofile)",
argv: ["sort", "-omalicious.sh"],
resolvedPath: "/usr/bin/sort",
expected: false,
safeBins: ["sort"],
executableName: "sort",
},
{
name: "blocks sort output path via --output=file",
argv: ["sort", "--output=malicious.sh"],
resolvedPath: "/usr/bin/sort",
expected: false,
safeBins: ["sort"],
executableName: "sort",
},
{
name: "blocks grep recursive flags that read cwd",
argv: ["grep", "-R", "needle"],
resolvedPath: "/usr/bin/grep",
expected: false,
safeBins: ["grep"],
executableName: "grep",
},
];
for (const testCase of cases) {
@@ -448,14 +484,16 @@ describe("exec approvals safe bins", () => {
}
const cwd = testCase.cwd ?? makeTempDir();
testCase.setup?.(cwd);
const executableName = testCase.executableName ?? "jq";
const rawExecutable = testCase.rawExecutable ?? executableName;
const ok = isSafeBinUsage({
argv: testCase.argv,
resolution: {
rawExecutable: "jq",
rawExecutable,
resolvedPath: testCase.resolvedPath,
executableName: "jq",
executableName,
},
safeBins: normalizeSafeBins(["jq"]),
safeBins: normalizeSafeBins(testCase.safeBins ?? [executableName]),
cwd,
});
expect(ok).toBe(testCase.expected);
@@ -479,6 +517,13 @@ describe("exec approvals safe bins", () => {
});
expect(ok).toBe(true);
});
it("does not include sort/grep in default safeBins", () => {
const defaults = resolveSafeBins(undefined);
expect(defaults.has("jq")).toBe(true);
expect(defaults.has("sort")).toBe(false);
expect(defaults.has("grep")).toBe(false);
});
});
describe("exec approvals allowlist evaluation", () => {