From 75f33e92bfb664f411b9a1d28ec625fcc5a63e55 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sun, 15 Feb 2026 19:40:07 +0000 Subject: [PATCH] fix(web): disallow workspace-* roots without explicit localRoots --- src/web/media.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/web/media.ts b/src/web/media.ts index f777dabdbbb..13ed96e492f 100644 --- a/src/web/media.ts +++ b/src/web/media.ts @@ -52,6 +52,24 @@ async function assertLocalMediaAllowed( } catch { resolved = path.resolve(mediaPath); } + + // Hardening: the default allowlist includes `os.tmpdir()`, and tests/CI may + // override the state dir into tmp. Avoid accidentally allowing per-agent + // `workspace-*` state roots via the tmpdir prefix match; require explicit + // localRoots for those. + if (localRoots === undefined) { + const workspaceRoot = roots.find((root) => path.basename(root) === "workspace"); + if (workspaceRoot) { + const stateDir = path.dirname(workspaceRoot); + const rel = path.relative(stateDir, resolved); + if (rel && !rel.startsWith("..") && !path.isAbsolute(rel)) { + const firstSegment = rel.split(path.sep)[0] ?? ""; + if (firstSegment.startsWith("workspace-")) { + throw new Error(`Local media path is not under an allowed directory: ${mediaPath}`); + } + } + } + } for (const root of roots) { let resolvedRoot: string; try {