fix(security): force sandbox browser hash migration and audit stale labels

This commit is contained in:
Peter Steinberger
2026-02-21 13:25:35 +01:00
parent b2d84528f8
commit 1835dec200
12 changed files with 254 additions and 6 deletions

View File

@@ -10,7 +10,11 @@ import { defaultRuntime } from "../../runtime.js";
import { BROWSER_BRIDGES } from "./browser-bridges.js";
import { computeSandboxBrowserConfigHash } from "./config-hash.js";
import { resolveSandboxBrowserDockerCreateConfig } from "./config.js";
import { DEFAULT_SANDBOX_BROWSER_IMAGE, SANDBOX_AGENT_WORKSPACE_MOUNT } from "./constants.js";
import {
DEFAULT_SANDBOX_BROWSER_IMAGE,
SANDBOX_AGENT_WORKSPACE_MOUNT,
SANDBOX_BROWSER_SECURITY_HASH_EPOCH,
} from "./constants.js";
import {
buildSandboxCreateArgs,
dockerContainerState,
@@ -125,6 +129,7 @@ export async function ensureSandboxBrowser(params: {
headless: params.cfg.browser.headless,
enableNoVnc: params.cfg.browser.enableNoVnc,
},
securityEpoch: SANDBOX_BROWSER_SECURITY_HASH_EPOCH,
workspaceAccess: params.cfg.workspaceAccess,
workspaceDir: params.workspaceDir,
agentWorkspaceDir: params.agentWorkspaceDir,
@@ -177,7 +182,10 @@ export async function ensureSandboxBrowser(params: {
name: containerName,
cfg: browserDockerCfg,
scopeKey: params.scopeKey,
labels: { "openclaw.sandboxBrowser": "1" },
labels: {
"openclaw.sandboxBrowser": "1",
"openclaw.browserConfigEpoch": SANDBOX_BROWSER_SECURITY_HASH_EPOCH,
},
configHash: expectedHash,
});
const mainMountSuffix =

View File

@@ -115,6 +115,7 @@ describe("computeSandboxBrowserConfigHash", () => {
headless: false,
enableNoVnc: true,
},
securityEpoch: "epoch-v1",
workspaceAccess: "rw" as const,
workspaceDir: "/tmp/workspace",
agentWorkspaceDir: "/tmp/workspace",
@@ -133,4 +134,29 @@ describe("computeSandboxBrowserConfigHash", () => {
});
expect(left).not.toBe(right);
});
it("changes when security epoch changes", () => {
const shared = {
docker: createDockerConfig(),
browser: {
cdpPort: 9222,
vncPort: 5900,
noVncPort: 6080,
headless: false,
enableNoVnc: true,
},
workspaceAccess: "rw" as const,
workspaceDir: "/tmp/workspace",
agentWorkspaceDir: "/tmp/workspace",
};
const left = computeSandboxBrowserConfigHash({
...shared,
securityEpoch: "epoch-v1",
});
const right = computeSandboxBrowserConfigHash({
...shared,
securityEpoch: "epoch-v2",
});
expect(left).not.toBe(right);
});
});

View File

@@ -14,6 +14,7 @@ type SandboxBrowserHashInput = {
SandboxBrowserConfig,
"cdpPort" | "vncPort" | "noVncPort" | "headless" | "enableNoVnc"
>;
securityEpoch: string;
workspaceAccess: SandboxWorkspaceAccess;
workspaceDir: string;
agentWorkspaceDir: string;

View File

@@ -38,6 +38,7 @@ export const DEFAULT_TOOL_DENY = [
export const DEFAULT_SANDBOX_BROWSER_IMAGE = "openclaw-sandbox-browser:bookworm-slim";
export const DEFAULT_SANDBOX_COMMON_IMAGE = "openclaw-sandbox-common:bookworm-slim";
export const SANDBOX_BROWSER_SECURITY_HASH_EPOCH = "2026-02-21-no-sandbox-default";
export const DEFAULT_SANDBOX_BROWSER_PREFIX = "openclaw-sbx-browser-";
export const DEFAULT_SANDBOX_BROWSER_CDP_PORT = 9222;