fix(node-host): sync rawCommand with hardened argv after executable path pinning (#33137)

Merged via squash.

Prepared head SHA: a7987905f7
Co-authored-by: Sid-Qin <201593046+Sid-Qin@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
This commit is contained in:
Sid
2026-03-05 00:30:33 +08:00
committed by GitHub
parent 4fb40497d4
commit c8ebd48e0f
4 changed files with 77 additions and 2 deletions

View File

@@ -2,6 +2,7 @@ import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { describe, expect, it } from "vitest";
import { formatExecCommand } from "../infra/system-run-command.js";
import {
buildSystemRunApprovalPlan,
hardenApprovedExecutionPaths,
@@ -18,7 +19,9 @@ type HardeningCase = {
shellCommand?: string | null;
withPathToken?: boolean;
expectedArgv: (ctx: { pathToken: PathTokenSetup | null }) => string[];
expectedArgvChanged?: boolean;
expectedCmdText?: string;
checkRawCommandMatchesArgv?: boolean;
};
describe("hardenApprovedExecutionPaths", () => {
@@ -36,6 +39,7 @@ describe("hardenApprovedExecutionPaths", () => {
argv: ["env", "tr", "a", "b"],
shellCommand: null,
expectedArgv: () => ["env", "tr", "a", "b"],
expectedArgvChanged: false,
},
{
name: "pins direct PATH-token executable during approval hardening",
@@ -44,6 +48,7 @@ describe("hardenApprovedExecutionPaths", () => {
shellCommand: null,
withPathToken: true,
expectedArgv: ({ pathToken }) => [pathToken!.expected, "SAFE"],
expectedArgvChanged: true,
},
{
name: "preserves env-wrapper PATH-token argv during approval hardening",
@@ -52,6 +57,15 @@ describe("hardenApprovedExecutionPaths", () => {
shellCommand: null,
withPathToken: true,
expectedArgv: () => ["env", "poccmd", "SAFE"],
expectedArgvChanged: false,
},
{
name: "rawCommand matches hardened argv after executable path pinning",
mode: "build-plan",
argv: ["poccmd", "hello"],
withPathToken: true,
expectedArgv: ({ pathToken }) => [pathToken!.expected, "hello"],
checkRawCommandMatchesArgv: true,
},
];
@@ -82,6 +96,9 @@ describe("hardenApprovedExecutionPaths", () => {
if (testCase.expectedCmdText) {
expect(prepared.cmdText).toBe(testCase.expectedCmdText);
}
if (testCase.checkRawCommandMatchesArgv) {
expect(prepared.plan.rawCommand).toBe(formatExecCommand(prepared.plan.argv));
}
return;
}
@@ -96,6 +113,9 @@ describe("hardenApprovedExecutionPaths", () => {
throw new Error("unreachable");
}
expect(hardened.argv).toEqual(testCase.expectedArgv({ pathToken }));
if (typeof testCase.expectedArgvChanged === "boolean") {
expect(hardened.argvChanged).toBe(testCase.expectedArgvChanged);
}
} finally {
if (testCase.withPathToken) {
if (oldPath === undefined) {