google-gemini/gemini-cli · error · Error
Workspace path ${resolvedPath} is outside the allowed root d
Error message
Workspace path ${resolvedPath} is outside the allowed root directory What it means
Thrown by validateWorkspacePath when the resolved workspace path does not lie under the allowed root. The allowed root is CODER_AGENT_ALLOWED_ROOT if set, otherwise homedir() in production (or the filesystem root / the tmpdir in test environments). path.relative(allowedRoot, resolvedPath) starting with '..' or being absolute means the workspace escaped the sandbox.
Source
Thrown at packages/a2a-server/src/config/config.ts:469
);
} else {
throw err;
}
}
const isTestEnv =
process.env['VITEST'] === 'true' ||
process.env['NODE_ENV'] === 'test' ||
process.argv.some((arg) => arg.includes('vitest')) ||
resolvedPath.startsWith(resolveToRealPath(tmpdir()));
const allowedRoot = resolveToRealPath(
getEnv('CODER_AGENT_ALLOWED_ROOT') ||
(isTestEnv ? path.parse(resolvedPath).root : homedir()),
);
const relative = path.relative(allowedRoot, resolvedPath);
if (relative.startsWith('..') || path.isAbsolute(relative)) {
throw new Error(
`Workspace path ${resolvedPath} is outside the allowed root directory`,
);
}
let stats: fs.Stats;
try {
stats = await fs.promises.stat(resolvedPath);
} catch (err: unknown) {
if (
err &&
typeof err === 'object' &&
'code' in err &&
err.code === 'ENOENT'
) {
if (isTestEnv) {
await fs.promises.mkdir(resolvedPath, { recursive: true });
stats = await fs.promises.stat(resolvedPath);
} else {View on GitHub (pinned to 5024443c72)
Solutions
- Set CODER_AGENT_ALLOWED_ROOT to a directory that contains the workspace (e.g. the repo root or /).
- Move the workspace under the user's home directory.
- If using symlinks, ensure the link target is within the allowed root.
- In test/CI, confirm NODE_ENV=test or VITEST=true is set so the test-env branch (root allowed root) applies.
Example fix
# before export CODER_AGENT_WORKSPACE_PATH=/workspace/myproj # throws: outside allowed root (default homedir) # after export CODER_AGENT_ALLOWED_ROOT=/workspace export CODER_AGENT_WORKSPACE_PATH=/workspace/myproj
Defensive patterns
Strategy: validation
Validate before calling
import path from 'node:path';
import { homedir } from 'node:os';
function assertWorkspaceAllowed(workspace: string) {
const root = process.env['CODER_AGENT_ALLOWED_ROOT'] || homedir();
const rel = path.relative(root, path.resolve(workspace));
if (rel.startsWith('..') || path.isAbsolute(rel)) {
throw new Error(`Workspace ${workspace} outside allowed root ${root}. Set CODER_AGENT_ALLOWED_ROOT.`);
}
} Prevention
- Set CODER_AGENT_ALLOWED_ROOT explicitly in any non-home deployment (CI, containers).
- Resolve symlinks before comparing - resolveToRealPath dereferences, so test the real target.
- In tests, ensure NODE_ENV=test or VITEST=true so the test-env branch (root allowed root) applies.
- Document the allowed-root contract in your deploy runbook.
When it happens
Trigger: CODER_AGENT_WORKSPACE_PATH resolves to a directory outside the user's home and CODER_AGENT_ALLOWED_ROOT is unset; symlink resolution (resolveToRealPath) dereferences a workspace symlink to a path outside the allowed root; allowed root misconfigured to a parent that doesn't contain the workspace.
Common situations: CI runner whose home is /root but the checkout lives in /workspace; Docker container where the workspace is mounted outside the default home; developer pointing at /tmp/myproj without setting CODER_AGENT_ALLOWED_ROOT in non-test mode.
Related errors
- Path validation failed: ${pathError}
- Workspace path ${resolvedPath} does not exist
- Workspace path ${resolvedPath} is not a directory
- Security violation: The path "${trimmedPath}" is outside the
- Invalid regex pattern in allowedExtensions setting: "${patte
AI-assisted analysis of google-gemini/gemini-cli@5024443c72 (2026-08-12).
Data as JSON: /api/errors/e08d2985b0d3ecd8.
Report an issue: GitHub.