refactor: dedupe exec wrapper denial plan and test setup

This commit is contained in:
Peter Steinberger
2026-02-25 00:43:19 +00:00
parent 943b8f171a
commit a9ce6bd79b
3 changed files with 140 additions and 125 deletions

View File

@@ -24,6 +24,14 @@ import {
type ExecAllowlistEntry,
} from "./exec-approvals.js";
function buildNestedEnvShellCommand(params: {
envExecutable: string;
depth: number;
payload: string;
}): string[] {
return [...Array(params.depth).fill(params.envExecutable), "/bin/sh", "-c", params.payload];
}
describe("exec approvals allowlist matching", () => {
const baseResolution = {
rawExecutable: "rg",
@@ -311,7 +319,11 @@ describe("exec approvals command resolution", () => {
fs.chmodSync(envPath, 0o755);
const analysis = analyzeArgvCommand({
argv: [envPath, envPath, envPath, envPath, envPath, "/bin/sh", "-c", "echo pwned"],
argv: buildNestedEnvShellCommand({
envExecutable: envPath,
depth: 5,
payload: "echo pwned",
}),
cwd: dir,
env: makePathEnv(binDir),
});

View File

@@ -448,6 +448,19 @@ function isSemanticDispatchWrapperUsage(wrapper: string, argv: string[]): boolea
return !TRANSPARENT_DISPATCH_WRAPPERS.has(wrapper);
}
function blockedDispatchWrapperPlan(params: {
argv: string[];
wrappers: string[];
blockedWrapper: string;
}): DispatchWrapperExecutionPlan {
return {
argv: params.argv,
wrappers: params.wrappers,
policyBlocked: true,
blockedWrapper: params.blockedWrapper,
};
}
export function resolveDispatchWrapperExecutionPlan(
argv: string[],
maxDepth = MAX_DISPATCH_WRAPPER_DEPTH,
@@ -457,36 +470,33 @@ export function resolveDispatchWrapperExecutionPlan(
for (let depth = 0; depth < maxDepth; depth += 1) {
const unwrap = unwrapKnownDispatchWrapperInvocation(current);
if (unwrap.kind === "blocked") {
return {
return blockedDispatchWrapperPlan({
argv: current,
wrappers,
policyBlocked: true,
blockedWrapper: unwrap.wrapper,
};
});
}
if (unwrap.kind !== "unwrapped" || unwrap.argv.length === 0) {
break;
}
wrappers.push(unwrap.wrapper);
if (isSemanticDispatchWrapperUsage(unwrap.wrapper, current)) {
return {
return blockedDispatchWrapperPlan({
argv: current,
wrappers,
policyBlocked: true,
blockedWrapper: unwrap.wrapper,
};
});
}
current = unwrap.argv;
}
if (wrappers.length >= maxDepth) {
const overflow = unwrapKnownDispatchWrapperInvocation(current);
if (overflow.kind === "blocked" || overflow.kind === "unwrapped") {
return {
return blockedDispatchWrapperPlan({
argv: current,
wrappers,
policyBlocked: true,
blockedWrapper: overflow.wrapper,
};
});
}
}
return { argv: current, wrappers, policyBlocked: false };