google-gemini/gemini-cli · critical
Security violation: The path "${trimmedPath}" is outside the
Error message
Security violation: The path "${trimmedPath}" is outside the allowed root directory. What it means
After resolving both the allowed root and the workspace path to their canonical (real, symlink-resolved) filesystem paths, the function checks containment. If the workspace path is neither identical to the root nor a strict subdirectory of it, it throws to prevent access outside the sandboxed root.
Source
Thrown at packages/a2a-server/src/utils/path_utils.ts:45
if (trimmedPath.includes('\0')) {
throw new Error('Security violation: Null byte detected in path.');
}
try {
const canonicalAllowedRoot = resolveToRealPath(allowedRoot);
const resolvedWorkspacePath = path.resolve(
canonicalAllowedRoot,
trimmedPath,
);
const canonicalWorkspacePath = resolveToRealPath(resolvedWorkspacePath);
// Check if the resolved path is within the allowed root directory
if (
canonicalWorkspacePath !== canonicalAllowedRoot &&
!isSubpath(canonicalAllowedRoot, canonicalWorkspacePath)
) {
throw new Error(
`Security violation: The path "${trimmedPath}" is outside the allowed root directory.`,
);
}
const stats = await fs.promises.stat(canonicalWorkspacePath);
if (!stats.isDirectory()) {
throw new Error(`The path "${trimmedPath}" is not a directory.`);
}
return canonicalWorkspacePath;
} catch (e) {
if (e instanceof Error && 'code' in e && e.code === 'ENOENT') {
throw new Error(`The path "${trimmedPath}" does not exist.`);
}
throw e; // Re-throw other errors
}
}
View on GitHub (pinned to 5024443c72)
Solutions
- Ensure the workspace path is relative and stays within the root without ../ escapes.
- Resolve symlinks before calling the function to understand the real filesystem target.
- Only use paths returned by trusted discovery mechanisms within the workspace.
- Verify that process.cwd() (the default allowedRoot) is set to the intended sandbox root.
Defensive patterns
Strategy: validation
Validate before calling
import { resolveToRealPath, isSubpath } from '@google/gemini-cli-core';
import * as path from 'node:path';
function isWithinRoot(candidate: string, root: string): boolean {
const canonicalRoot = resolveToRealPath(root);
const canonicalCandidate = resolveToRealPath(path.resolve(canonicalRoot, candidate));
return canonicalCandidate === canonicalRoot || isSubpath(canonicalRoot, canonicalCandidate);
}
// Before calling validateWorkspacePath:
if (!isWithinRoot(userPath, allowedRoot)) {
throw new Error('Path escapes the allowed root');
} Prevention
- Only use relative paths returned by trusted in-workspace discovery mechanisms.
- Resolve and inspect symlinks before treating a path as workspace-relative.
- Set the allowedRoot explicitly rather than relying on process.cwd() defaults.
- Reject any user input containing '..' segments at the input boundary.
When it happens
Trigger: Passing a relative path with ../ sequences that escape the root (e.g., validateWorkspacePath('../../etc', '/home/user/project')), or an absolute path pointing outside the root, or a path that resolves through a symlink to a location outside the allowed root.
Common situations: Symlinks within the workspace that point outside it; relative paths with excessive parent directory traversals; user-supplied paths not validated upstream; incorrect allowedRoot default (process.cwd() is not what was expected).
Related errors
- Path validation failed: ${pathError}
- Invalid taskId: ${taskId}
- Security violation: Null byte detected in path.
- Invalid path: Directory traversal not allowed.
- Invalid skill name: Path traversal detected.
AI-assisted analysis of google-gemini/gemini-cli@5024443c72 (2026-08-12).
Data as JSON: /api/errors/c4496c1c460e838f.
Report an issue: GitHub.