fix(security): properly test Windows ACL audit for config includes

The test expected fs.config_include.perms_writable on Windows but
chmod 0o644 has no effect on Windows ACLs. Use icacls to grant
Everyone write access, which properly triggers the security check.

Also stubs execIcacls to return proper ACL output so the audit
can parse permissions without running actual icacls on the system.

Adds cleanup via try/finally to remove temp directory containing
world-writable test file.

Fixes checks-windows CI failure.
This commit is contained in:
Dominic 2026-01-26 15:37:08 -06:00 committed by Tyler Yust
parent 343882d45c
commit 6f61e2dd84

View File

@ -857,12 +857,19 @@ describe("security audit", () => {
const includePath = path.join(stateDir, "extra.json5"); const includePath = path.join(stateDir, "extra.json5");
await fs.writeFile(includePath, "{ logging: { redactSensitive: 'off' } }\n", "utf-8"); await fs.writeFile(includePath, "{ logging: { redactSensitive: 'off' } }\n", "utf-8");
if (isWindows) {
// Grant "Everyone" write access to trigger the perms_writable check on Windows
const { execSync } = await import("node:child_process");
execSync(`icacls "${includePath}" /grant Everyone:W`, { stdio: "ignore" });
} else {
await fs.chmod(includePath, 0o644); await fs.chmod(includePath, 0o644);
}
const configPath = path.join(stateDir, "clawdbot.json"); const configPath = path.join(stateDir, "clawdbot.json");
await fs.writeFile(configPath, `{ "$include": "./extra.json5" }\n`, "utf-8"); await fs.writeFile(configPath, `{ "$include": "./extra.json5" }\n`, "utf-8");
await fs.chmod(configPath, 0o600); await fs.chmod(configPath, 0o600);
try {
const cfg: ClawdbotConfig = { logging: { redactSensitive: "off" } }; const cfg: ClawdbotConfig = { logging: { redactSensitive: "off" } };
const user = "DESKTOP-TEST\\Tester"; const user = "DESKTOP-TEST\\Tester";
const execIcacls = isWindows const execIcacls = isWindows
@ -902,6 +909,10 @@ describe("security audit", () => {
expect.objectContaining({ checkId: expectedCheckId, severity: "critical" }), expect.objectContaining({ checkId: expectedCheckId, severity: "critical" }),
]), ]),
); );
} finally {
// Clean up temp directory with world-writable file
await fs.rm(tmp, { recursive: true, force: true });
}
}); });
it("flags extensions without plugins.allow", async () => { it("flags extensions without plugins.allow", async () => {