Skip to content

Commit 0ca7f3e

Browse files
Remove skill prelude exec allowlist
1 parent 9b6fba4 commit 0ca7f3e

2 files changed

Lines changed: 81 additions & 0 deletions

File tree

src/agents/bash-tools.exec.approval-id.test.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1274,6 +1274,65 @@ describe("exec approvals", () => {
12741274
}
12751275
});
12761276

1277+
it("requires approval for the legacy skill display prelude even when the wrapper is allowlisted", async () => {
1278+
if (process.platform === "win32") {
1279+
return;
1280+
}
1281+
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-skill-prelude-"));
1282+
try {
1283+
const skillDir = path.join(tempDir, ".openclaw", "skills", "gog");
1284+
const skillPath = path.join(skillDir, "SKILL.md");
1285+
const binDir = path.join(tempDir, "bin");
1286+
const wrapperPath = path.join(binDir, "gog-wrapper");
1287+
await fs.mkdir(skillDir, { recursive: true });
1288+
await fs.mkdir(binDir, { recursive: true });
1289+
await fs.writeFile(skillPath, "# gog skill\n");
1290+
await fs.writeFile(wrapperPath, "#!/bin/sh\necho '{\"events\":[]}'\n");
1291+
await fs.chmod(wrapperPath, 0o755);
1292+
const trustedWrapperPath = await fs.realpath(wrapperPath);
1293+
1294+
await writeExecApprovalsConfig({
1295+
version: 1,
1296+
defaults: { security: "allowlist", ask: "on-miss", askFallback: "deny" },
1297+
agents: {
1298+
main: {
1299+
allowlist: [{ pattern: trustedWrapperPath }],
1300+
},
1301+
},
1302+
});
1303+
1304+
const calls: string[] = [];
1305+
vi.mocked(callGatewayTool).mockImplementation(async (method, _opts, params) => {
1306+
calls.push(method);
1307+
if (method === "exec.approval.request") {
1308+
return acceptedApprovalResponse(params);
1309+
}
1310+
if (method === "exec.approval.waitDecision") {
1311+
return { decision: "deny" };
1312+
}
1313+
return { ok: true };
1314+
});
1315+
1316+
const tool = createExecTool({
1317+
host: "gateway",
1318+
ask: "on-miss",
1319+
security: "allowlist",
1320+
approvalRunningNoticeMs: 0,
1321+
});
1322+
1323+
const command = `cat ${JSON.stringify(skillPath)} && printf '\\n---CMD---\\n' && ${JSON.stringify(wrapperPath)} calendar events primary --today --json`;
1324+
const result = await tool.execute("call-skill-prelude", {
1325+
command,
1326+
workdir: tempDir,
1327+
});
1328+
1329+
expectPendingCommandText(result, command);
1330+
expect(calls).toContain("exec.approval.request");
1331+
} finally {
1332+
await fs.rm(tempDir, { recursive: true, force: true });
1333+
}
1334+
});
1335+
12771336
it("shows full chained node commands in approval-pending message", async () => {
12781337
const calls: string[] = [];
12791338
vi.mocked(callGatewayTool).mockImplementation(async (method, _opts, params) => {

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,28 @@ describe("exec approvals shell analysis", () => {
624624
expect(result.segmentSatisfiedBy).toEqual(["allowlist"]);
625625
});
626626

627+
it("rejects the legacy skill display prelude when only the wrapper is allowlisted", () => {
628+
if (process.platform === "win32") {
629+
return;
630+
}
631+
const { skillRoot, wrapperPath } = createSkillWrapperFixture();
632+
const skillDir = path.join(skillRoot, "skills", "gog");
633+
const skillPath = path.join(skillDir, "SKILL.md");
634+
fs.mkdirSync(skillDir, { recursive: true });
635+
fs.writeFileSync(skillPath, "# gog\n");
636+
637+
const result = evaluateShellAllowlist({
638+
command: `cat ${skillPath} && printf '\\n---CMD---\\n' && ${wrapperPath} calendar events primary --today --json`,
639+
allowlist: [{ pattern: wrapperPath }],
640+
safeBins: new Set(),
641+
cwd: skillRoot,
642+
});
643+
644+
expect(result.analysisOk).toBe(true);
645+
expect(result.allowlistSatisfied).toBe(false);
646+
expect(result.segmentSatisfiedBy).toEqual([null]);
647+
});
648+
627649
it.each(['/usr/bin/echo "foo && bar"', '/usr/bin/echo "foo\\" && bar"'])(
628650
"respects quoted chain separator for %s",
629651
(command) => {

0 commit comments

Comments
 (0)