Skip to content

Commit 30de507

Browse files
committed
addressing codex review
1 parent df046b0 commit 30de507

4 files changed

Lines changed: 48 additions & 1 deletion

File tree

src/infra/exec-approvals-analysis.test.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -796,6 +796,35 @@ describe("exec approvals shell analysis", () => {
796796
}
797797
});
798798

799+
it("rejects PowerShell inline argv payloads with trailing command tokens", () => {
800+
const dir = makeTempDir();
801+
const allowedPath = path.join(dir, "allowed.exe");
802+
fs.writeFileSync(allowedPath, "");
803+
fs.chmodSync(allowedPath, 0o755);
804+
try {
805+
const env = makePathEnv(dir);
806+
const analysis = analyzeArgvCommand({
807+
argv: ["pwsh", "-Command", "allowed.exe", ";", "unlisted.exe"],
808+
cwd: dir,
809+
env,
810+
});
811+
expect(analysis.ok).toBe(true);
812+
const result = evaluateExecAllowlist({
813+
analysis,
814+
allowlist: [{ pattern: allowedPath }],
815+
safeBins: new Set(),
816+
cwd: dir,
817+
env,
818+
platform: "win32",
819+
});
820+
expect(result.allowlistSatisfied).toBe(false);
821+
expect(result.segmentAllowlistEntries).toEqual([null]);
822+
expect(result.segmentSatisfiedBy).toEqual([null]);
823+
} finally {
824+
fs.rmSync(dir, { recursive: true, force: true });
825+
}
826+
});
827+
799828
it("satisfies allowlist when bare * wildcard is present", () => {
800829
const dir = makeTempDir();
801830
const binPath = path.join(dir, "mybin");

src/infra/exec-wrapper-resolution.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,11 @@ describe("extractShellWrapperCommand", () => {
483483
expectedInline: "Get-Date",
484484
expectedCommand: { isWrapper: true, command: "Get-Date" },
485485
},
486+
{
487+
argv: ["pwsh", "-Command", "allowed.exe", ";", "unlisted.exe"],
488+
expectedInline: "allowed.exe ; unlisted.exe",
489+
expectedCommand: { isWrapper: true, command: "allowed.exe ; unlisted.exe" },
490+
},
486491
{
487492
argv: ["cmd.exe", "-c", "echo", "hi"],
488493
expectedInline: "echo hi",

src/infra/shell-wrapper-resolution.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,16 @@ function extractCmdInlineCommand(argv: string[]): string | null {
217217
}
218218

219219
function extractPowerShellInlineCommand(argv: string[]): string | null {
220-
return extractInlineCommandByFlags(argv, POWERSHELL_INLINE_COMMAND_FLAGS);
220+
const match = resolveInlineCommandMatch(argv, POWERSHELL_INLINE_COMMAND_FLAGS);
221+
if (match.command === null || match.valueTokenIndex === null) {
222+
return match.command;
223+
}
224+
const flag = normalizeLowercaseStringOrEmpty(argv[match.valueTokenIndex - 1]);
225+
if (flag === "-command" || flag === "-c" || flag === "--command") {
226+
const command = argv.slice(match.valueTokenIndex).join(" ").trim();
227+
return command.length > 0 ? command : null;
228+
}
229+
return match.command;
221230
}
222231

223232
function extractInlineCommandByFlags(

src/infra/system-run-command.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ describe("system run command helpers", () => {
7777
},
7878
{ argv: ["fish", "-c", "echo hi"], expected: "echo hi" },
7979
{ argv: ["pwsh", "-Command", "Get-Date"], expected: "Get-Date" },
80+
{
81+
argv: ["pwsh", "-Command", "allowed.exe", ";", "unlisted.exe"],
82+
expected: "allowed.exe ; unlisted.exe",
83+
},
8084
{ argv: ["pwsh", "-File", "script.ps1"], expected: "script.ps1" },
8185
{ argv: ["powershell", "-f", "script.ps1"], expected: "script.ps1" },
8286
{ argv: ["pwsh", "-ec", "ZQBjAGgAbwA="], expected: "ZQBjAGgAbwA=" },

0 commit comments

Comments
 (0)