test: merge audit browser container cases

This commit is contained in:
Peter Steinberger 2026-03-17 09:21:36 +00:00
parent 355051f401
commit 2cfccf59c7

View File

@ -850,120 +850,113 @@ description: test skill
).toBe(true);
});
it("warns when sandbox browser containers have missing or stale hash labels", async () => {
const { stateDir, configPath } = await createFilesystemAuditFixture("browser-hash-labels");
it("evaluates sandbox browser container findings", async () => {
const cases = [
{
name: "warns when sandbox browser containers have missing or stale hash labels",
fixtureLabel: "browser-hash-labels",
execDockerRawFn: (async (args: string[]) => {
if (args[0] === "ps") {
return {
stdout: Buffer.from("openclaw-sbx-browser-old\nopenclaw-sbx-browser-missing-hash\n"),
stderr: Buffer.alloc(0),
code: 0,
};
}
if (args[0] === "inspect" && args.at(-1) === "openclaw-sbx-browser-old") {
return {
stdout: Buffer.from("abc123\tepoch-v0\n"),
stderr: Buffer.alloc(0),
code: 0,
};
}
if (args[0] === "inspect" && args.at(-1) === "openclaw-sbx-browser-missing-hash") {
return {
stdout: Buffer.from("<no value>\t<no value>\n"),
stderr: Buffer.alloc(0),
code: 0,
};
}
return {
stdout: Buffer.alloc(0),
stderr: Buffer.from("not found"),
code: 1,
};
}) as NonNullable<SecurityAuditOptions["execDockerRawFn"]>,
assert: (res: SecurityAuditReport) => {
expect(hasFinding(res, "sandbox.browser_container.hash_label_missing", "warn")).toBe(
true,
);
expect(hasFinding(res, "sandbox.browser_container.hash_epoch_stale", "warn")).toBe(true);
const staleEpoch = res.findings.find(
(f) => f.checkId === "sandbox.browser_container.hash_epoch_stale",
);
expect(staleEpoch?.detail).toContain("openclaw-sbx-browser-old");
},
},
{
name: "skips sandbox browser hash label checks when docker inspect is unavailable",
fixtureLabel: "browser-hash-labels-skip",
execDockerRawFn: (async () => {
throw new Error("spawn docker ENOENT");
}) as NonNullable<SecurityAuditOptions["execDockerRawFn"]>,
assert: (res: SecurityAuditReport) => {
expect(hasFinding(res, "sandbox.browser_container.hash_label_missing")).toBe(false);
expect(hasFinding(res, "sandbox.browser_container.hash_epoch_stale")).toBe(false);
},
},
{
name: "flags sandbox browser containers with non-loopback published ports",
fixtureLabel: "browser-non-loopback-publish",
execDockerRawFn: (async (args: string[]) => {
if (args[0] === "ps") {
return {
stdout: Buffer.from("openclaw-sbx-browser-exposed\n"),
stderr: Buffer.alloc(0),
code: 0,
};
}
if (args[0] === "inspect" && args.at(-1) === "openclaw-sbx-browser-exposed") {
return {
stdout: Buffer.from("hash123\t2026-02-21-novnc-auth-default\n"),
stderr: Buffer.alloc(0),
code: 0,
};
}
if (args[0] === "port" && args.at(-1) === "openclaw-sbx-browser-exposed") {
return {
stdout: Buffer.from("6080/tcp -> 0.0.0.0:49101\n9222/tcp -> 127.0.0.1:49100\n"),
stderr: Buffer.alloc(0),
code: 0,
};
}
return {
stdout: Buffer.alloc(0),
stderr: Buffer.from("not found"),
code: 1,
};
}) as NonNullable<SecurityAuditOptions["execDockerRawFn"]>,
assert: (res: SecurityAuditReport) => {
expect(
hasFinding(res, "sandbox.browser_container.non_loopback_publish", "critical"),
).toBe(true);
},
},
] as const;
const execDockerRawFn = (async (args: string[]) => {
if (args[0] === "ps") {
return {
stdout: Buffer.from("openclaw-sbx-browser-old\nopenclaw-sbx-browser-missing-hash\n"),
stderr: Buffer.alloc(0),
code: 0,
};
}
if (args[0] === "inspect" && args.at(-1) === "openclaw-sbx-browser-old") {
return {
stdout: Buffer.from("abc123\tepoch-v0\n"),
stderr: Buffer.alloc(0),
code: 0,
};
}
if (args[0] === "inspect" && args.at(-1) === "openclaw-sbx-browser-missing-hash") {
return {
stdout: Buffer.from("<no value>\t<no value>\n"),
stderr: Buffer.alloc(0),
code: 0,
};
}
return {
stdout: Buffer.alloc(0),
stderr: Buffer.from("not found"),
code: 1,
};
}) as NonNullable<SecurityAuditOptions["execDockerRawFn"]>;
const res = await runSecurityAudit({
config: {},
includeFilesystem: true,
includeChannelSecurity: false,
stateDir,
configPath,
execDockerRawFn,
});
expect(hasFinding(res, "sandbox.browser_container.hash_label_missing", "warn")).toBe(true);
expect(hasFinding(res, "sandbox.browser_container.hash_epoch_stale", "warn")).toBe(true);
const staleEpoch = res.findings.find(
(f) => f.checkId === "sandbox.browser_container.hash_epoch_stale",
);
expect(staleEpoch?.detail).toContain("openclaw-sbx-browser-old");
});
it("skips sandbox browser hash label checks when docker inspect is unavailable", async () => {
const { stateDir, configPath } = await createFilesystemAuditFixture("browser-hash-labels-skip");
const execDockerRawFn = (async () => {
throw new Error("spawn docker ENOENT");
}) as NonNullable<SecurityAuditOptions["execDockerRawFn"]>;
const res = await runSecurityAudit({
config: {},
includeFilesystem: true,
includeChannelSecurity: false,
stateDir,
configPath,
execDockerRawFn,
});
expect(hasFinding(res, "sandbox.browser_container.hash_label_missing")).toBe(false);
expect(hasFinding(res, "sandbox.browser_container.hash_epoch_stale")).toBe(false);
});
it("flags sandbox browser containers with non-loopback published ports", async () => {
const { stateDir, configPath } = await createFilesystemAuditFixture(
"browser-non-loopback-publish",
);
const execDockerRawFn = (async (args: string[]) => {
if (args[0] === "ps") {
return {
stdout: Buffer.from("openclaw-sbx-browser-exposed\n"),
stderr: Buffer.alloc(0),
code: 0,
};
}
if (args[0] === "inspect" && args.at(-1) === "openclaw-sbx-browser-exposed") {
return {
stdout: Buffer.from("hash123\t2026-02-21-novnc-auth-default\n"),
stderr: Buffer.alloc(0),
code: 0,
};
}
if (args[0] === "port" && args.at(-1) === "openclaw-sbx-browser-exposed") {
return {
stdout: Buffer.from("6080/tcp -> 0.0.0.0:49101\n9222/tcp -> 127.0.0.1:49100\n"),
stderr: Buffer.alloc(0),
code: 0,
};
}
return {
stdout: Buffer.alloc(0),
stderr: Buffer.from("not found"),
code: 1,
};
}) as NonNullable<SecurityAuditOptions["execDockerRawFn"]>;
const res = await runSecurityAudit({
config: {},
includeFilesystem: true,
includeChannelSecurity: false,
stateDir,
configPath,
execDockerRawFn,
});
expect(hasFinding(res, "sandbox.browser_container.non_loopback_publish", "critical")).toBe(
true,
await Promise.all(
cases.map(async (testCase) => {
const { stateDir, configPath } = await createFilesystemAuditFixture(testCase.fixtureLabel);
const res = await runSecurityAudit({
config: {},
includeFilesystem: true,
includeChannelSecurity: false,
stateDir,
configPath,
execDockerRawFn: testCase.execDockerRawFn,
});
testCase.assert(res);
}),
);
});