mastra-ai/mastra · error
Path escapes workspace root: ${inputPath}
Error message
Path escapes workspace root: ${inputPath} What it means
This sandboxed filesystem resolves every user-supplied path against the workspace root and refuses anything that lexically normalizes outside it. The library throws this to enforce the sandbox boundary: even a path like `a/../../etc/passwd` or an absolute path pointing at a sibling directory is rejected before any shell command runs. It is a deliberate security guard, not a bug.
Source
Thrown at mastracode/sdk/src/agents/sandbox-filesystem.ts:165
* Accepts both workspace-relative paths (`src/foo.ts`, `/src/foo.ts`) and
* absolute sandbox paths that already live under the workdir — the agent's
* prompt advertises the workdir as its working directory, so tools are
* routinely called with fully-qualified paths like `<workdir>/src/foo.ts`.
*/
private resolveAgainst(basePath: string, inputPath: string): string {
const base = posixPath.normalize(basePath);
const normalizedInput = posixPath.normalize(inputPath);
const rel =
normalizedInput === base
? ''
: normalizedInput.startsWith(`${base}/`)
? normalizedInput.slice(base.length + 1)
: inputPath.startsWith('/')
? inputPath.slice(1)
: inputPath;
const resolved = posixPath.normalize(posixPath.join(base, rel));
if (resolved !== base && !resolved.startsWith(`${base}/`)) {
throw new Error(`Path escapes workspace root: ${inputPath}`);
}
return resolved;
}
resolveAbsolutePath(inputPath: string): string | undefined {
// Sync interface: a lazy workdir that has not resolved yet has no
// absolute form to offer.
if (!this.resolvedBase) return undefined;
return this.resolveAgainst(this.resolvedBase, inputPath);
}
// ── Command helper ─────────────────────────────────────────────────────
private async exec(script: string): Promise<SandboxCommandResult> {
return this.sandbox.executeCommand('sh', ['-c', script], { timeout: COMMAND_TIMEOUT_MS });
}
/**View on GitHub (pinned to 75dd419e61)
Solutions
- Remove `..` segments or rewrite the path so it resolves inside the workspace root
- If the target genuinely lives outside the root, move it into the workspace or reconfigure the sandbox workdir to encompass it
- Normalize/validate caller-supplied paths (e.g. path.resolve then checking containment) before passing them to the sandbox API
Example fix
// before
await fs.resolveAsync('../outside/secret.txt'); // throws
// after
await fs.resolveAsync('outside/secret.txt'); // stays within workspace root Defensive patterns
Strategy: validation
Validate before calling
import path from 'node:path';
export function isInsideRoot(root: string, input: string): boolean {
const resolvedInput = path.resolve(root, input);
const resolvedRoot = path.resolve(root);
return resolvedInput === resolvedRoot || resolvedInput.startsWith(resolvedRoot + path.sep);
}
if (!isInsideRoot(WORKSPACE_ROOT, userInput)) throw new Error('Path must stay inside the workspace root'); Type guard
function isSafeWorkspacePath(p: string): boolean {
const norm = path.posix.normalize(p.replace(/^\//, ''));
return !norm.startsWith('..') && norm !== '..' && !path.posix.isAbsolute(norm);
} Try / catch
try {
const resolved = await fs.resolveAsync(inputPath);
} catch (err) {
if (err instanceof Error && err.message.startsWith('Path escapes workspace root')) {
// reject/ask for corrected path; never retry with the same input
}
throw err;
} Prevention
- Normalize and containment-check user/LLM-provided paths before handing them to the sandbox API
- Never concatenate raw absolute host paths into sandbox path arguments
- Configure the sandbox workdir high enough to cover all paths the workload needs
- Strip or reject `..` segments in any path template or interpolated input
When it happens
Trigger: Calling resolveAsync, resolveAbsolutePath, or any file operation built on resolveAgainst with a path containing `..` segments that escape the root (e.g. `../secrets.txt`, `a/../../x`), or an absolute path that does not fall under the configured workspace root base.
Common situations: Passing an absolute host path (e.g. `/home/user/file`) into a sandbox whose root is a different directory; joining a workspace-external temp dir; resolving symlink-like or user-provided paths that contain `..`; configuring the sandbox workdir lower in the tree than the paths the agent tries to touch.
Related errors
- ${label} escapes workspace
- Path is outside the browsable root
- Path escapes workspace
- Path is outside the workspace
- Root escapes workspace
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/7f0be3f4d11b5023.
Report an issue: GitHub.