fix(media): require staged sandbox media refs

This commit is contained in:
Peter Steinberger
2026-05-27 03:08:41 +01:00
parent 8d6b599737
commit 42d6cf66d3
2 changed files with 33 additions and 0 deletions

View File

@@ -49,18 +49,24 @@ describe("createSandboxBridgeReadFile", () => {
relativePath: filePath,
containerPath: `/sandbox/${filePath}`,
}));
const stat = vi.fn(async () => ({ type: "file", size: 1, mtimeMs: 1 }));
const resolved = await resolveSandboxedBridgeMediaPath({
sandbox: {
root: "/tmp/sandbox-root",
bridge: {
resolvePath,
stat,
} as unknown as SandboxFsBridge,
},
mediaPath: "media://inbound/photo.png",
inboundFallbackDir: "media/inbound",
});
expect(stat).toHaveBeenCalledWith({
filePath: "media/inbound/photo.png",
cwd: "/tmp/sandbox-root",
});
expect(resolvePath).toHaveBeenCalledWith({
filePath: "media/inbound/photo.png",
cwd: "/tmp/sandbox-root",
@@ -70,4 +76,22 @@ describe("createSandboxBridgeReadFile", () => {
rewrittenFrom: "media://inbound/photo.png",
});
});
it("rejects missing staged inbound media URIs before direct sandbox resolution", async () => {
const resolvePath = vi.fn();
await expect(
resolveSandboxedBridgeMediaPath({
sandbox: {
root: "/tmp/sandbox-root",
bridge: {
resolvePath,
stat: vi.fn(async () => null),
} as unknown as SandboxFsBridge,
},
mediaPath: "media://inbound/missing.png",
inboundFallbackDir: "media/inbound",
}),
).rejects.toThrow("Sandbox media reference is not staged: media://inbound/missing.png");
expect(resolvePath).not.toHaveBeenCalled();
});
});

View File

@@ -31,6 +31,15 @@ export async function resolveSandboxedBridgeMediaPath(params: {
: { resolved: params.mediaPath };
const filePath = normalizeFileUrl(mediaPathInfo.resolved);
const rewrittenFrom = mediaPathInfo.rewrittenFrom;
if (rewrittenFrom) {
const stat = await params.sandbox.bridge.stat({
filePath,
cwd: params.sandbox.root,
});
if (!stat) {
throw new Error(`Sandbox media reference is not staged: ${rewrittenFrom}`);
}
}
const enforceWorkspaceBoundary = async (hostPath: string) => {
if (!params.sandbox.workspaceOnly) {
return;