vercel/ai · error
'HarnessAgent: `sandboxConfig.workDir` must stay inside the
Error message
'HarnessAgent: `sandboxConfig.workDir` must stay inside the sandbox default working directory.'
What it means
After posix.normalize, the workDir must not be '.', '..' or start with '../' — i.e. it must stay inside the sandbox's default working directory. Escaping via '..' would let the sandbox touch files outside its designated root, so it is rejected as a safety invariant.
Source
Thrown at packages/harness/src/agent/internal/sandbox-bootstrap.ts:61
'HarnessAgent: `sandboxConfig.workDir` must not contain NUL.',
);
}
if (workDir.includes('\\')) {
throw new Error(
'HarnessAgent: `sandboxConfig.workDir` must use POSIX path separators.',
);
}
if (posix.isAbsolute(workDir)) {
throw new Error('HarnessAgent: `sandboxConfig.workDir` must be relative.');
}
const normalized = posix.normalize(workDir);
if (
normalized === '.' ||
normalized === '..' ||
normalized.startsWith('../')
) {
throw new Error(
'HarnessAgent: `sandboxConfig.workDir` must stay inside the sandbox default working directory.',
);
}
return normalized;
}
export function resolveSessionWorkDir({
defaultWorkingDirectory,
harnessId,
sessionId,
workDir,
}: {
readonly defaultWorkingDirectory: string;
readonly harnessId: string;
readonly sessionId: string;
readonly workDir?: string;
}): string {
return joinSandboxPath({View on GitHub (pinned to 69428b1f8b)
Solutions
- Change workDir to a path that stays under the default working directory, e.g. 'runs/latest' instead of '../shared'.
- Verify with path.posix.normalize(workDir) in your own code that the result is not '.' / '..' / '../...'.
- If you need data from outside, mount/copy it into the sandbox rather than traversing upward.
Example fix
// before const workDir = '../shared-output'; // after const workDir = 'shared-output'; // stays inside the sandbox default work dir
Defensive patterns
Strategy: validation
Validate before calling
const n = path.posix.normalize(workDir); if (n === '.' || n === '..' || n.startsWith('../')) throw new Error('workDir escapes sandbox root'); Type guard
function isContainedPath(v: string): boolean { const n = path.posix.normalize(v); return n !== '.' && n !== '..' && !n.startsWith('../'); } Try / catch
try { await prepareSandboxForHarness({ sandboxConfig: { workDir }, harnesses }); } catch (e) { if (e.message.includes('stay inside')) { /* reject config or clamp path */ } else throw e; } Prevention
- Normalize and check every user-supplied path before passing it in
- Never construct workDir by joining with '..'
- Treat path containment as a security invariant in code review
When it happens
Trigger: Passing sandboxConfig.workDir values like '..', './..', 'a/../../etc', or any path that normalizes to a parent of the default working directory.
Common situations: Trying to share a directory from outside the work root via traversal; computing a relative path from the wrong base so the result escapes upward.
Related errors
- 'HarnessAgent: `sandboxConfig.workDir` must not contain NUL.
- 'HarnessAgent: `sandboxConfig.workDir` must be relative.'
- Failed to resolve sandbox default working directory: expecte
- Tool approval signature verification failed for approval "${
- ACP runtime environment key ${JSON.stringify(key)} cannot be
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/f4e7acc12c1bf195.
Report an issue: GitHub.