mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-26 04:15:48 -06:00
fix(sandbox): normalize protected mount destinations
This commit is contained in:
@@ -599,6 +599,7 @@ describe("ensureSandboxContainer config-hash recreation", () => {
|
||||
const customMount = `${customRoot}:/workspace/skills:rw`;
|
||||
const cfg = createSandboxConfig([], [customMount]);
|
||||
cfg.backend = backend;
|
||||
cfg.docker.workdir = "/workspace/.";
|
||||
cfg.docker.dangerouslyAllowExternalBindSources = true;
|
||||
spawnState.inspectRunning = false;
|
||||
registryMocks.readRegistryEntry.mockResolvedValue(null);
|
||||
@@ -609,7 +610,7 @@ describe("ensureSandboxContainer config-hash recreation", () => {
|
||||
|
||||
expect(createCall.command).toBe(backend);
|
||||
expect(bindArgs).not.toContain(customMount);
|
||||
expect(bindArgs).toContain(`${path.join(workspaceDir, "skills")}:/workspace/skills:ro,z`);
|
||||
expect(bindArgs).toContain(`${path.join(workspaceDir, "skills")}:/workspace/./skills:ro,z`);
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -214,8 +214,10 @@ describe("resolveSandboxFsPathWithMounts", () => {
|
||||
const sandbox = createSandbox({
|
||||
workspaceDir,
|
||||
agentWorkspaceDir: workspaceDir,
|
||||
containerWorkdir: "/workspace/.",
|
||||
docker: {
|
||||
...createSandbox().docker,
|
||||
workdir: "/workspace/.",
|
||||
binds: [`${customRoot}:/workspace/skills:rw`],
|
||||
},
|
||||
});
|
||||
|
||||
@@ -265,7 +265,7 @@ describe("resolveProtectedSkillMountContainerPaths", () => {
|
||||
it("returns container paths from skill mounts", () => {
|
||||
const mounts: ReadOnlyWorkspaceSkillMount[] = [
|
||||
{ hostPath: "/host/skills", containerPath: "/workspace/skills" },
|
||||
{ hostPath: "/host/.agents/skills", containerPath: "/workspace/.agents/skills" },
|
||||
{ hostPath: "/host/.agents/skills", containerPath: "/workspace/./.agents/skills/" },
|
||||
];
|
||||
const paths = resolveProtectedSkillMountContainerPaths(mounts);
|
||||
expect(paths).toEqual(new Set(["/workspace/skills", "/workspace/.agents/skills"]));
|
||||
|
||||
@@ -38,6 +38,10 @@ function containerJoin(root: string, ...parts: string[]): string {
|
||||
return suffix ? `${normalizedRoot}/${suffix}` : normalizedRoot;
|
||||
}
|
||||
|
||||
function normalizeMountContainerPath(containerPath: string): string {
|
||||
return normalizeContainerPath(containerPath).replace(/\/+$/, "") || "/";
|
||||
}
|
||||
|
||||
/** Hidden workspace used to materialize non-workspace skills for rw sandboxes. */
|
||||
export function resolveMaterializedSandboxSkillsWorkspaceDir(rootDir: string): string {
|
||||
return path.join(rootDir, ...MATERIALIZED_SANDBOX_SKILLS_WORKSPACE_PARTS);
|
||||
@@ -126,7 +130,7 @@ export function formatReadOnlyWorkspaceSkillMountHashState(
|
||||
export function resolveProtectedSkillMountContainerPaths(
|
||||
mounts: readonly ReadOnlyWorkspaceSkillMount[],
|
||||
): Set<string> {
|
||||
return new Set(mounts.map((m) => m.containerPath));
|
||||
return new Set(mounts.map((mount) => normalizeMountContainerPath(mount.containerPath)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,8 +155,7 @@ export function filterBindsConflictingWithProtectedMounts(
|
||||
filtered.push(bind);
|
||||
continue;
|
||||
}
|
||||
// Strip trailing slashes so /workspace/skills/ matches /workspace/skills from containerJoin.
|
||||
const containerPath = normalizeContainerPath(spec.container).replace(/\/+$/, "") || "/";
|
||||
const containerPath = normalizeMountContainerPath(spec.container);
|
||||
if (!protectedContainerPaths.has(containerPath)) {
|
||||
filtered.push(bind);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user