refactor(exec): rename wrapper plans for trust semantics

This commit is contained in:
Peter Steinberger
2026-03-22 23:16:50 -07:00
parent 0b40ec38ab
commit cef7d14861
3 changed files with 14 additions and 19 deletions

View File

@@ -315,7 +315,7 @@ export type DispatchWrapperUnwrapResult =
| { kind: "blocked"; wrapper: string }
| { kind: "unwrapped"; wrapper: string; argv: string[] };
export type DispatchWrapperExecutionPlan = {
export type DispatchWrapperTrustPlan = {
argv: string[];
wrappers: string[];
policyBlocked: boolean;
@@ -358,7 +358,7 @@ export function unwrapDispatchWrappersForResolution(
argv: string[],
maxDepth = MAX_DISPATCH_WRAPPER_DEPTH,
): string[] {
const plan = resolveDispatchWrapperExecutionPlan(argv, maxDepth);
const plan = resolveDispatchWrapperTrustPlan(argv, maxDepth);
return plan.argv;
}
@@ -378,7 +378,7 @@ function blockedDispatchWrapperPlan(params: {
argv: string[];
wrappers: string[];
blockedWrapper: string;
}): DispatchWrapperExecutionPlan {
}): DispatchWrapperTrustPlan {
return {
argv: params.argv,
wrappers: params.wrappers,
@@ -387,10 +387,10 @@ function blockedDispatchWrapperPlan(params: {
};
}
export function resolveDispatchWrapperExecutionPlan(
export function resolveDispatchWrapperTrustPlan(
argv: string[],
maxDepth = MAX_DISPATCH_WRAPPER_DEPTH,
): DispatchWrapperExecutionPlan {
): DispatchWrapperTrustPlan {
let current = argv;
const wrappers: string[] = [];
for (let depth = 0; depth < maxDepth; depth += 1) {

View File

@@ -7,7 +7,7 @@ import {
isDispatchWrapperExecutable,
isShellWrapperExecutable,
normalizeExecutableToken,
resolveDispatchWrapperExecutionPlan,
resolveDispatchWrapperTrustPlan,
unwrapEnvInvocation,
unwrapKnownDispatchWrapperInvocation,
unwrapKnownShellMultiplexerInvocation,
@@ -154,9 +154,9 @@ describe("unwrapKnownDispatchWrapperInvocation", () => {
);
});
describe("resolveDispatchWrapperExecutionPlan", () => {
describe("resolveDispatchWrapperTrustPlan", () => {
test("allows non-semantic env passthrough", () => {
expect(resolveDispatchWrapperExecutionPlan(["env", "--", "bash", "-lc", "echo hi"])).toEqual({
expect(resolveDispatchWrapperTrustPlan(["env", "--", "bash", "-lc", "echo hi"])).toEqual({
argv: ["bash", "-lc", "echo hi"],
wrappers: ["env"],
policyBlocked: false,
@@ -196,7 +196,7 @@ describe("resolveDispatchWrapperExecutionPlan", () => {
wrapper,
argv: effectiveArgv,
});
expect(resolveDispatchWrapperExecutionPlan(argv)).toEqual({
expect(resolveDispatchWrapperTrustPlan(argv)).toEqual({
argv: effectiveArgv,
wrappers: [wrapper],
policyBlocked: false,
@@ -205,7 +205,7 @@ describe("resolveDispatchWrapperExecutionPlan", () => {
test("unwraps transparent wrapper chains", () => {
expect(
resolveDispatchWrapperExecutionPlan(["nohup", "nice", "-n", "5", "bash", "-lc", "echo hi"]),
resolveDispatchWrapperTrustPlan(["nohup", "nice", "-n", "5", "bash", "-lc", "echo hi"]),
).toEqual({
argv: ["bash", "-lc", "echo hi"],
wrappers: ["nohup", "nice"],
@@ -214,9 +214,7 @@ describe("resolveDispatchWrapperExecutionPlan", () => {
});
test("blocks semantic env usage even when it reaches a shell wrapper", () => {
expect(
resolveDispatchWrapperExecutionPlan(["env", "FOO=bar", "bash", "-lc", "echo hi"]),
).toEqual({
expect(resolveDispatchWrapperTrustPlan(["env", "FOO=bar", "bash", "-lc", "echo hi"])).toEqual({
argv: ["env", "FOO=bar", "bash", "-lc", "echo hi"],
wrappers: ["env"],
policyBlocked: true,
@@ -226,7 +224,7 @@ describe("resolveDispatchWrapperExecutionPlan", () => {
test("blocks wrapper overflow beyond the configured depth", () => {
expect(
resolveDispatchWrapperExecutionPlan(["nohup", "timeout", "5s", "bash", "-lc", "echo hi"], 1),
resolveDispatchWrapperTrustPlan(["nohup", "timeout", "5s", "bash", "-lc", "echo hi"], 1),
).toEqual({
argv: ["timeout", "5s", "bash", "-lc", "echo hi"],
wrappers: ["nohup"],

View File

@@ -1,6 +1,6 @@
import {
MAX_DISPATCH_WRAPPER_DEPTH,
resolveDispatchWrapperExecutionPlan,
resolveDispatchWrapperTrustPlan,
unwrapKnownDispatchWrapperInvocation,
} from "./dispatch-wrapper-resolution.js";
import {
@@ -59,10 +59,7 @@ export function resolveExecWrapperTrustPlan(
let current = argv;
const wrapperChain: string[] = [];
for (let depth = 0; depth < maxDepth; depth += 1) {
const dispatchPlan = resolveDispatchWrapperExecutionPlan(
current,
maxDepth - wrapperChain.length,
);
const dispatchPlan = resolveDispatchWrapperTrustPlan(current, maxDepth - wrapperChain.length);
if (dispatchPlan.policyBlocked) {
return blockedExecWrapperTrustPlan({
argv: dispatchPlan.argv,