fix(exec-approvals): match simple command name patterns in allowlist
Previously, matchAllowlist() skipped all patterns without path separators (like 'pwd', 'ls', 'date'), making it impossible to allowlist commands by their simple executable name. The bug was caused by 'if (!hasPath) continue;' which short-circuited before matching against executableName. Now simple patterns match against executableName, and path-based patterns fallback to rawExecutable when resolvedPath is undefined.
This commit is contained in:
parent
9daa846457
commit
4bef31e009
@ -33,7 +33,7 @@ function makeTempDir() {
|
||||
}
|
||||
|
||||
describe("exec approvals allowlist matching", () => {
|
||||
it("ignores basename-only patterns", () => {
|
||||
it("matches basename-only patterns case-insensitively", () => {
|
||||
const resolution = {
|
||||
rawExecutable: "rg",
|
||||
resolvedPath: "/opt/homebrew/bin/rg",
|
||||
@ -41,7 +41,7 @@ describe("exec approvals allowlist matching", () => {
|
||||
};
|
||||
const entries: ExecAllowlistEntry[] = [{ pattern: "RG" }];
|
||||
const match = matchAllowlist(entries, resolution);
|
||||
expect(match).toBeNull();
|
||||
expect(match?.pattern).toBe("RG");
|
||||
});
|
||||
|
||||
it("matches by resolved path with **", () => {
|
||||
@ -66,7 +66,7 @@ describe("exec approvals allowlist matching", () => {
|
||||
expect(match).toBeNull();
|
||||
});
|
||||
|
||||
it("requires a resolved path", () => {
|
||||
it("falls back to rawExecutable when resolvedPath is undefined", () => {
|
||||
const resolution = {
|
||||
rawExecutable: "bin/rg",
|
||||
resolvedPath: undefined,
|
||||
@ -74,7 +74,7 @@ describe("exec approvals allowlist matching", () => {
|
||||
};
|
||||
const entries: ExecAllowlistEntry[] = [{ pattern: "bin/rg" }];
|
||||
const match = matchAllowlist(entries, resolution);
|
||||
expect(match).toBeNull();
|
||||
expect(match?.pattern).toBe("bin/rg");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@ -508,14 +508,20 @@ export function matchAllowlist(
|
||||
entries: ExecAllowlistEntry[],
|
||||
resolution: CommandResolution | null,
|
||||
): ExecAllowlistEntry | null {
|
||||
if (!entries.length || !resolution?.resolvedPath) return null;
|
||||
if (!entries.length || !resolution) return null;
|
||||
const rawExecutable = resolution.rawExecutable;
|
||||
const resolvedPath = resolution.resolvedPath;
|
||||
const executableName = resolution.executableName;
|
||||
for (const entry of entries) {
|
||||
const pattern = entry.pattern?.trim();
|
||||
if (!pattern) continue;
|
||||
const hasPath = pattern.includes("/") || pattern.includes("\\") || pattern.includes("~");
|
||||
if (!hasPath) continue;
|
||||
if (matchesPattern(pattern, resolvedPath)) return entry;
|
||||
if (hasPath) {
|
||||
const target = resolvedPath ?? rawExecutable;
|
||||
if (target && matchesPattern(pattern, target)) return entry;
|
||||
continue;
|
||||
}
|
||||
if (executableName && matchesPattern(pattern, executableName)) return entry;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user