import { type Request, type Response } from 'express'; import { join, resolve, sep } from 'path'; export function getLocalWorkspacePath(worktreeDir: string | undefined, taskId: number): string { const base = worktreeDir ?? '/tmp/maestro/workspaces'; return join(base, 'local', String(taskId)); } export function ensurePathWithin(baseDir: string, requestedPath: string): string { const resolvedBase = resolve(baseDir); const resolvedPath = resolve(baseDir, requestedPath); if (!resolvedPath.startsWith(resolvedBase + sep) && resolvedPath !== resolvedBase) { throw new Error('Path escapes workspace'); } return resolvedPath; } /** * Harden a response that serves user/agent-authored workspace bytes. * * Workspace files can hold attacker-influenced HTML/SVG (an agent driven by a * poisoned web page, or another user's shared task). Without these headers the * browser renders such a file inline on the app origin and any embedded * `