if (!hasContainer) { if (noVncEnabled) {
noVncPassword = generateNoVncPassword();
}
await ensureDockerNetwork(browserDockerCfg.network, {
allowContainerNamespaceJoin: browserDockerCfg.dangerouslyAllowContainerNamespaceJoin === true,
});
await ensureSandboxBrowserImage(browserImage); // Derive effective CDP source range: explicit config > Docker network gateway > fail-closed. // Only IPv4 gateways are usable for auto-derivation because the CDP relay // binds on 0.0.0.0 (IPv4); an IPv6 CIDR would cause an address-family mismatch.
let effectiveCdpSourceRange = cdpSourceRange; if (!effectiveCdpSourceRange) { // Only auto-derive from gateway for bridge-style networks where inbound // CDP traffic reliably comes from the Docker gateway IP. Non-bridge drivers // (macvlan, ipvlan, overlay, etc.) may route traffic from other source IPs, // so they require explicit cdpSourceRange config. const driver = await readDockerNetworkDriver(browserDockerCfg.network); const isBridgeLike = !driver || driver === "bridge"; if (isBridgeLike) { const gateway = await readDockerNetworkGateway(browserDockerCfg.network); if (gateway && !gateway.includes(":")) {
effectiveCdpSourceRange = `${gateway}/32`;
}
}
} // network="none" has no IPAM gateway by design and no peer container risk; // use loopback range so the socat CDP relay still starts. if (!effectiveCdpSourceRange && browserDockerCfg.network.trim().toLowerCase() === "none") {
effectiveCdpSourceRange = "127.0.0.1/32";
} if (!effectiveCdpSourceRange) { thrownew Error(
`Cannot derive CDP source range for sandbox browser on network "${browserDockerCfg.network}". ` +
`Set agents.defaults.sandbox.browser.cdpSourceRange explicitly.`,
);
} const args = buildSandboxCreateArgs({
name: containerName,
cfg: browserDockerCfg,
scopeKey: params.scopeKey,
labels: { "openclaw.sandboxBrowser": "1", "openclaw.browserConfigEpoch": SANDBOX_BROWSER_SECURITY_HASH_EPOCH,
},
configHash: expectedHash,
includeBinds: false,
bindSourceRoots: [params.workspaceDir, params.agentWorkspaceDir],
});
appendWorkspaceMountArgs({
args,
workspaceDir: params.workspaceDir,
agentWorkspaceDir: params.agentWorkspaceDir,
workdir: params.cfg.docker.workdir,
workspaceAccess: params.cfg.workspaceAccess,
}); if (browserDockerCfg.binds?.length) { for (const bind of browserDockerCfg.binds) {
args.push("-v", bind);
}
}
args.push("-p", `127.0.0.1::${params.cfg.browser.cdpPort}`); if (noVncEnabled) {
args.push("-p", `127.0.0.1::${params.cfg.browser.noVncPort}`);
}
args.push("-e", `OPENCLAW_BROWSER_HEADLESS=${params.cfg.browser.headless ? "1" : "0"}`);
args.push("-e", `OPENCLAW_BROWSER_ENABLE_NOVNC=${params.cfg.browser.enableNoVnc ? "1" : "0"}`);
args.push("-e", `OPENCLAW_BROWSER_CDP_PORT=${params.cfg.browser.cdpPort}`);
args.push( "-e",
`OPENCLAW_BROWSER_AUTO_START_TIMEOUT_MS=${params.cfg.browser.autoStartTimeoutMs}`,
); if (effectiveCdpSourceRange) {
args.push("-e", `${CDP_SOURCE_RANGE_ENV_KEY}=${effectiveCdpSourceRange}`);
}
args.push("-e", `OPENCLAW_BROWSER_VNC_PORT=${params.cfg.browser.vncPort}`);
args.push("-e", `OPENCLAW_BROWSER_NOVNC_PORT=${params.cfg.browser.noVncPort}`);
args.push("-e", "OPENCLAW_BROWSER_NO_SANDBOX=1"); if (noVncEnabled && noVncPassword) {
args.push("-e", `${NOVNC_PASSWORD_ENV_KEY}=${noVncPassword}`);
}
args.push(browserImage);
await execDocker(args);
await execDocker(["start", containerName]);
} elseif (!running) {
await execDocker(["start", containerName]);
}
const mappedCdp = await readDockerPort(containerName, params.cfg.browser.cdpPort); if (!mappedCdp) { thrownew Error(`Failed to resolve CDP port mapping for ${containerName}.`);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.