diff --git a/src/web/media.test.ts b/src/web/media.test.ts index dc8eff56131..3573f5afb15 100644 --- a/src/web/media.test.ts +++ b/src/web/media.test.ts @@ -332,4 +332,31 @@ describe("local media root guard", () => { const result = await loadWebMedia(tinyPngFile, 1024 * 1024, { localRoots: "any" }); expect(result.kind).toBe("image"); }); + + it("allows default OpenClaw state workspace and sandbox roots", async () => { + const { STATE_DIR } = await import("../config/paths.js"); + const readFile = vi.fn(async () => Buffer.from("generated-media")); + + await expect( + loadWebMedia(path.join(STATE_DIR, "workspace", "tmp", "render.bin"), { + maxBytes: 1024 * 1024, + readFile, + }), + ).resolves.toEqual( + expect.objectContaining({ + kind: "unknown", + }), + ); + + await expect( + loadWebMedia(path.join(STATE_DIR, "sandboxes", "session-1", "frame.bin"), { + maxBytes: 1024 * 1024, + readFile, + }), + ).resolves.toEqual( + expect.objectContaining({ + kind: "unknown", + }), + ); + }); }); diff --git a/src/web/media.ts b/src/web/media.ts index 244d6767ec0..cf7efd5f49c 100644 --- a/src/web/media.ts +++ b/src/web/media.ts @@ -3,6 +3,7 @@ import os from "node:os"; import path from "node:path"; import { fileURLToPath } from "node:url"; import type { SsrFPolicy } from "../infra/net/ssrf.js"; +import { STATE_DIR } from "../config/paths.js"; import { logVerbose, shouldLogVerbose } from "../globals.js"; import { type MediaKind, maxBytesForKind, mediaKindFromMime } from "../media/constants.js"; import { fetchRemoteMedia } from "../media/fetch.js"; @@ -32,11 +33,12 @@ type WebMediaOptions = { }; function getDefaultLocalRoots(): string[] { - const home = os.homedir(); return [ os.tmpdir(), - path.join(home, ".openclaw", "media"), - path.join(home, ".openclaw", "agents"), + path.join(STATE_DIR, "media"), + path.join(STATE_DIR, "agents"), + path.join(STATE_DIR, "workspace"), + path.join(STATE_DIR, "sandboxes"), ]; }