




























@@ -920,7 +920,7 @@ describe("handleSystemRunInvoke mac app exec host routing", () => {
920920});
921921922922for (const runtime of ["bun", "deno", "tsx", "jiti"] as const) {
923-it(`denies approval-based execution when a ${runtime} script operand changes after approval`, async () => {
923+it(`validates approved ${runtime} script operand stability`, async () => {
924924await withFakeRuntimeOnPath({
925925 runtime,
926926run: async () => {
@@ -959,23 +959,15 @@ describe("handleSystemRunInvoke mac app exec host routing", () => {
959959} finally {
960960fs.rmSync(tmp, { recursive: true, force: true });
961961}
962-},
963-});
964-});
965-966-it(`keeps approved ${runtime} script execution working when the script is unchanged`, async () => {
967-await withFakeRuntimeOnPath({
968- runtime,
969-run: async () => {
970-const tmp = fs.mkdtempSync(
962+const stableTmp = fs.mkdtempSync(
971963path.join(os.tmpdir(), `openclaw-approval-${runtime}-script-stable-`),
972964);
973-const fixture = createRuntimeScriptOperandFixture({ tmp, runtime });
974-fs.writeFileSync(fixture.scriptPath, fixture.initialBody);
965+const stableFixture = createRuntimeScriptOperandFixture({ tmp: stableTmp, runtime });
966+fs.writeFileSync(stableFixture.scriptPath, stableFixture.initialBody);
975967try {
976968const prepared = buildSystemRunApprovalPlan({
977-command: fixture.command,
978-cwd: tmp,
969+command: stableFixture.command,
970+cwd: stableTmp,
979971});
980972expect(prepared.ok).toBe(true);
981973if (!prepared.ok) {
@@ -987,7 +979,7 @@ describe("handleSystemRunInvoke mac app exec host routing", () => {
987979command: prepared.plan.argv,
988980rawCommand: prepared.plan.commandText,
989981systemRunPlan: prepared.plan,
990-cwd: prepared.plan.cwd ?? tmp,
982+cwd: prepared.plan.cwd ?? stableTmp,
991983approved: true,
992984security: "full",
993985ask: "off",
@@ -996,7 +988,7 @@ describe("handleSystemRunInvoke mac app exec host routing", () => {
996988expect(runCommand).toHaveBeenCalledTimes(1);
997989expectInvokeOk(sendInvokeResult);
998990} finally {
999-fs.rmSync(tmp, { recursive: true, force: true });
991+fs.rmSync(stableTmp, { recursive: true, force: true });
1000992}
1001993},
1002994});
@@ -1310,32 +1302,33 @@ describe("handleSystemRunInvoke mac app exec host routing", () => {
13101302});
13111303});
131213041313-it.each([
1314-{
1315-command: ["python3", "-c", "print('hi')"],
1316-expected: "python3 -c requires explicit approval in strictInlineEval mode",
1317-},
1318-{
1319-command: ["awk", 'BEGIN{system("id")}', "/dev/null"],
1320-expected: "awk inline program requires explicit approval in strictInlineEval mode",
1321-},
1322-{
1323-command: ["find", ".", "-exec", "id", "{}", ";"],
1324-expected: "find -exec requires explicit approval in strictInlineEval mode",
1325-},
1326-{
1327-command: ["xargs", "id"],
1328-expected: "xargs inline command requires explicit approval in strictInlineEval mode",
1329-},
1330-{
1331-command: ["make", "-f", "evil.mk"],
1332-expected: "make -f requires explicit approval in strictInlineEval mode",
1333-},
1334-{
1335-command: ["sed", "s/.*/id/e", "/dev/null"],
1336-expected: "sed inline program requires explicit approval in strictInlineEval mode",
1337-},
1338-] as const)("requires explicit approval for strict inline-eval carrier %j", async (testCase) => {
1305+it("requires explicit approval for strict inline-eval carriers", async () => {
1306+const cases = [
1307+{
1308+command: ["python3", "-c", "print('hi')"],
1309+expected: "python3 -c requires explicit approval in strictInlineEval mode",
1310+},
1311+{
1312+command: ["awk", 'BEGIN{system("id")}', "/dev/null"],
1313+expected: "awk inline program requires explicit approval in strictInlineEval mode",
1314+},
1315+{
1316+command: ["find", ".", "-exec", "id", "{}", ";"],
1317+expected: "find -exec requires explicit approval in strictInlineEval mode",
1318+},
1319+{
1320+command: ["xargs", "id"],
1321+expected: "xargs inline command requires explicit approval in strictInlineEval mode",
1322+},
1323+{
1324+command: ["make", "-f", "evil.mk"],
1325+expected: "make -f requires explicit approval in strictInlineEval mode",
1326+},
1327+{
1328+command: ["sed", "s/.*/id/e", "/dev/null"],
1329+expected: "sed inline program requires explicit approval in strictInlineEval mode",
1330+},
1331+] as const;
13391332setRuntimeConfigSnapshot({
13401333tools: {
13411334exec: {
@@ -1344,22 +1337,24 @@ describe("handleSystemRunInvoke mac app exec host routing", () => {
13441337},
13451338});
13461339try {
1347-const { runCommand, sendInvokeResult, sendNodeEvent } = await runSystemInvoke({
1348-preferMacAppExecHost: false,
1349-command: [...testCase.command],
1350-security: "full",
1351-ask: "off",
1352-});
1340+for (const testCase of cases) {
1341+const { runCommand, sendInvokeResult, sendNodeEvent } = await runSystemInvoke({
1342+preferMacAppExecHost: false,
1343+command: [...testCase.command],
1344+security: "full",
1345+ask: "off",
1346+});
135313471354-expect(runCommand).not.toHaveBeenCalled();
1355-expect(sendNodeEvent).toHaveBeenCalledWith(
1356-expect.anything(),
1357-"exec.denied",
1358-expect.objectContaining({ reason: "approval-required" }),
1359-);
1360-expectInvokeErrorMessage(sendInvokeResult, {
1361-message: testCase.expected,
1362-});
1348+expect(runCommand, testCase.command.join(" ")).not.toHaveBeenCalled();
1349+expect(sendNodeEvent, testCase.command.join(" ")).toHaveBeenCalledWith(
1350+expect.anything(),
1351+"exec.denied",
1352+expect.objectContaining({ reason: "approval-required" }),
1353+);
1354+expectInvokeErrorMessage(sendInvokeResult, {
1355+message: testCase.expected,
1356+});
1357+}
13631358} finally {
13641359clearRuntimeConfigSnapshot();
13651360}
@@ -1395,26 +1390,26 @@ describe("handleSystemRunInvoke mac app exec host routing", () => {
13951390}
13961391});
139713921398-it.each([
1399-{ executable: "python3", args: ["-c", "print('hi')"] },
1400-{ executable: "awk", args: ['BEGIN{system("id")}', "/dev/null"] },
1401-{ executable: "find", args: [".", "-exec", "id", "{}", ";"] },
1402-{ executable: "xargs", args: ["id"] },
1403-{ executable: "sed", args: ["s/.*/id/e", "/dev/null"] },
1404-] as const)(
1405-"does not persist allow-always approvals for strict inline-eval carrier %j",
1406-async (testCase) => {
1407-setRuntimeConfigSnapshot({
1408-tools: {
1409-exec: {
1410-strictInlineEval: true,
1411-},
1393+it("does not persist allow-always approvals for strict inline-eval carriers", async () => {
1394+const cases = [
1395+{ executable: "python3", args: ["-c", "print('hi')"] },
1396+{ executable: "awk", args: ['BEGIN{system("id")}', "/dev/null"] },
1397+{ executable: "find", args: [".", "-exec", "id", "{}", ";"] },
1398+{ executable: "xargs", args: ["id"] },
1399+{ executable: "sed", args: ["s/.*/id/e", "/dev/null"] },
1400+] as const;
1401+setRuntimeConfigSnapshot({
1402+tools: {
1403+exec: {
1404+strictInlineEval: true,
14121405},
1413-});
1414-try {
1415-await withTempApprovalsHome({
1416-approvals: createAllowlistOnMissApprovals(),
1417-run: async () => {
1406+},
1407+});
1408+try {
1409+await withTempApprovalsHome({
1410+approvals: createAllowlistOnMissApprovals(),
1411+run: async () => {
1412+for (const testCase of cases) {
14181413const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "openclaw-inline-eval-bin-"));
14191414try {
14201415const executablePath = createTempExecutable({
@@ -1437,13 +1432,13 @@ describe("handleSystemRunInvoke mac app exec host routing", () => {
14371432} finally {
14381433fs.rmSync(tempDir, { recursive: true, force: true });
14391434}
1440-},
1441-});
1442-} finally {
1443- clearRuntimeConfigSnapshot();
1444-}
1445-},
1446-);
1435+}
1436+},
1437+});
1438+} finally {
1439+clearRuntimeConfigSnapshot();
1440+}
1441+});
1447144214481443it("persists benign awk allow-always approvals in strict inline-eval mode without reopening inline carriers", async () => {
14491444setRuntimeConfigSnapshot({
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。