mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-10 13:05:01 +00:00
test(sandbox): table-drive dangerous docker config rejection cases
This commit is contained in:
@@ -2,6 +2,40 @@ import { describe, expect, it } from "vitest";
|
|||||||
import { buildSandboxCreateArgs, type SandboxDockerConfig } from "./sandbox.js";
|
import { buildSandboxCreateArgs, type SandboxDockerConfig } from "./sandbox.js";
|
||||||
|
|
||||||
describe("buildSandboxCreateArgs", () => {
|
describe("buildSandboxCreateArgs", () => {
|
||||||
|
function createSandboxConfig(
|
||||||
|
overrides: Partial<SandboxDockerConfig> = {},
|
||||||
|
binds?: string[],
|
||||||
|
): SandboxDockerConfig {
|
||||||
|
return {
|
||||||
|
image: "openclaw-sandbox:bookworm-slim",
|
||||||
|
containerPrefix: "openclaw-sbx-",
|
||||||
|
workdir: "/workspace",
|
||||||
|
readOnlyRoot: false,
|
||||||
|
tmpfs: [],
|
||||||
|
network: "none",
|
||||||
|
capDrop: [],
|
||||||
|
...(binds ? { binds } : {}),
|
||||||
|
...overrides,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function expectBuildToThrow(
|
||||||
|
name: string,
|
||||||
|
cfg: SandboxDockerConfig,
|
||||||
|
expectedMessage: RegExp,
|
||||||
|
): void {
|
||||||
|
expect(
|
||||||
|
() =>
|
||||||
|
buildSandboxCreateArgs({
|
||||||
|
name,
|
||||||
|
cfg,
|
||||||
|
scopeKey: "main",
|
||||||
|
createdAtMs: 1700000000000,
|
||||||
|
}),
|
||||||
|
name,
|
||||||
|
).toThrow(expectedMessage);
|
||||||
|
}
|
||||||
|
|
||||||
it("includes hardening and resource flags", () => {
|
it("includes hardening and resource flags", () => {
|
||||||
const cfg: SandboxDockerConfig = {
|
const cfg: SandboxDockerConfig = {
|
||||||
image: "openclaw-sandbox:bookworm-slim",
|
image: "openclaw-sandbox:bookworm-slim",
|
||||||
@@ -127,113 +161,39 @@ describe("buildSandboxCreateArgs", () => {
|
|||||||
expect(vFlags).toContain("/var/data/myapp:/data:ro");
|
expect(vFlags).toContain("/var/data/myapp:/data:ro");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("throws on dangerous bind mounts (Docker socket)", () => {
|
it.each([
|
||||||
const cfg: SandboxDockerConfig = {
|
{
|
||||||
image: "openclaw-sandbox:bookworm-slim",
|
name: "dangerous Docker socket bind mounts",
|
||||||
containerPrefix: "openclaw-sbx-",
|
containerName: "openclaw-sbx-dangerous",
|
||||||
workdir: "/workspace",
|
cfg: createSandboxConfig({}, ["/var/run/docker.sock:/var/run/docker.sock"]),
|
||||||
readOnlyRoot: false,
|
expected: /blocked path/,
|
||||||
tmpfs: [],
|
},
|
||||||
network: "none",
|
{
|
||||||
capDrop: [],
|
name: "dangerous parent bind mounts",
|
||||||
binds: ["/var/run/docker.sock:/var/run/docker.sock"],
|
containerName: "openclaw-sbx-dangerous-parent",
|
||||||
};
|
cfg: createSandboxConfig({}, ["/run:/run"]),
|
||||||
|
expected: /blocked path/,
|
||||||
expect(() =>
|
},
|
||||||
buildSandboxCreateArgs({
|
{
|
||||||
name: "openclaw-sbx-dangerous",
|
name: "network host mode",
|
||||||
cfg,
|
containerName: "openclaw-sbx-host",
|
||||||
scopeKey: "main",
|
cfg: createSandboxConfig({ network: "host" }),
|
||||||
createdAtMs: 1700000000000,
|
expected: /network mode "host" is blocked/,
|
||||||
}),
|
},
|
||||||
).toThrow(/blocked path/);
|
{
|
||||||
});
|
name: "seccomp unconfined",
|
||||||
|
containerName: "openclaw-sbx-seccomp",
|
||||||
it("throws on dangerous bind mounts (parent path)", () => {
|
cfg: createSandboxConfig({ seccompProfile: "unconfined" }),
|
||||||
const cfg: SandboxDockerConfig = {
|
expected: /seccomp profile "unconfined" is blocked/,
|
||||||
image: "openclaw-sandbox:bookworm-slim",
|
},
|
||||||
containerPrefix: "openclaw-sbx-",
|
{
|
||||||
workdir: "/workspace",
|
name: "apparmor unconfined",
|
||||||
readOnlyRoot: false,
|
containerName: "openclaw-sbx-apparmor",
|
||||||
tmpfs: [],
|
cfg: createSandboxConfig({ apparmorProfile: "unconfined" }),
|
||||||
network: "none",
|
expected: /apparmor profile "unconfined" is blocked/,
|
||||||
capDrop: [],
|
},
|
||||||
binds: ["/run:/run"],
|
])("throws on $name", ({ containerName, cfg, expected }) => {
|
||||||
};
|
expectBuildToThrow(containerName, cfg, expected);
|
||||||
|
|
||||||
expect(() =>
|
|
||||||
buildSandboxCreateArgs({
|
|
||||||
name: "openclaw-sbx-dangerous-parent",
|
|
||||||
cfg,
|
|
||||||
scopeKey: "main",
|
|
||||||
createdAtMs: 1700000000000,
|
|
||||||
}),
|
|
||||||
).toThrow(/blocked path/);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("throws on network host mode", () => {
|
|
||||||
const cfg: SandboxDockerConfig = {
|
|
||||||
image: "openclaw-sandbox:bookworm-slim",
|
|
||||||
containerPrefix: "openclaw-sbx-",
|
|
||||||
workdir: "/workspace",
|
|
||||||
readOnlyRoot: false,
|
|
||||||
tmpfs: [],
|
|
||||||
network: "host",
|
|
||||||
capDrop: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(() =>
|
|
||||||
buildSandboxCreateArgs({
|
|
||||||
name: "openclaw-sbx-host",
|
|
||||||
cfg,
|
|
||||||
scopeKey: "main",
|
|
||||||
createdAtMs: 1700000000000,
|
|
||||||
}),
|
|
||||||
).toThrow(/network mode "host" is blocked/);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("throws on seccomp unconfined", () => {
|
|
||||||
const cfg: SandboxDockerConfig = {
|
|
||||||
image: "openclaw-sandbox:bookworm-slim",
|
|
||||||
containerPrefix: "openclaw-sbx-",
|
|
||||||
workdir: "/workspace",
|
|
||||||
readOnlyRoot: false,
|
|
||||||
tmpfs: [],
|
|
||||||
network: "none",
|
|
||||||
capDrop: [],
|
|
||||||
seccompProfile: "unconfined",
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(() =>
|
|
||||||
buildSandboxCreateArgs({
|
|
||||||
name: "openclaw-sbx-seccomp",
|
|
||||||
cfg,
|
|
||||||
scopeKey: "main",
|
|
||||||
createdAtMs: 1700000000000,
|
|
||||||
}),
|
|
||||||
).toThrow(/seccomp profile "unconfined" is blocked/);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("throws on apparmor unconfined", () => {
|
|
||||||
const cfg: SandboxDockerConfig = {
|
|
||||||
image: "openclaw-sandbox:bookworm-slim",
|
|
||||||
containerPrefix: "openclaw-sbx-",
|
|
||||||
workdir: "/workspace",
|
|
||||||
readOnlyRoot: false,
|
|
||||||
tmpfs: [],
|
|
||||||
network: "none",
|
|
||||||
capDrop: [],
|
|
||||||
apparmorProfile: "unconfined",
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(() =>
|
|
||||||
buildSandboxCreateArgs({
|
|
||||||
name: "openclaw-sbx-apparmor",
|
|
||||||
cfg,
|
|
||||||
scopeKey: "main",
|
|
||||||
createdAtMs: 1700000000000,
|
|
||||||
}),
|
|
||||||
).toThrow(/apparmor profile "unconfined" is blocked/);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("omits -v flags when binds is empty or undefined", () => {
|
it("omits -v flags when binds is empty or undefined", () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user