alibaba/spring-ai-alibaba · warning · IllegalArgumentException
Path: outside root directory:
Error message
Path: outside root directory:
What it means
In virtualMode, after resolving and normalizing the requested key against the backend's cwd, resolvePath() verifies the result still starts with cwd; if normalization (e.g. via symlinks-in-path or .. already caught, but also absolute segments) escapes the root it throws IllegalArgumentException("Path:<full> outside root directory: <cwd>"). This is the second layer of the virtual-root sandbox.
Source
Thrown at spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/extension/file/LocalFilesystemBackend.java:109
}
/**
* Resolve a file path with security checks.
*
* When virtualMode=True, treat incoming paths as virtual absolute paths under
* cwd, disallow traversal (.., ~) and ensure resolved path stays within root.
* When virtualMode=False, preserve legacy behavior: absolute paths are allowed
* as-is; relative paths resolve under cwd.
*/
private Path resolvePath(String key) throws IllegalArgumentException {
if (virtualMode) {
String vpath = key.startsWith("/") ? key : "/" + key;
if (vpath.contains("..") || vpath.startsWith("~")) {
throw new IllegalArgumentException("Path traversal not allowed");
}
Path full = cwd.resolve(vpath.substring(1)).normalize();
if (!full.startsWith(cwd)) {
throw new IllegalArgumentException("Path:" + full + " outside root directory: " + cwd);
}
return full;
}
Path path = Paths.get(key);
if (path.isAbsolute()) {
return path;
}
return cwd.resolve(path).normalize();
}
@Override
public List<FileInfo> lsInfo(String path) {
try {
Path dirPath = resolvePath(path);
if (!Files.exists(dirPath) || !Files.isDirectory(dirPath)) {
return Collections.emptyList();
}View on GitHub (pinned to f82da0b50f)
Solutions
- Use paths located under the configured cwd/root directory.
- Reconfigure the backend's cwd (virtual root) to encompass the required directory tree.
- Normalize and prefix external absolute paths relative to the root before passing them.
- Check the normalized path with full.startsWith(root) in your own code first for a clearer error message.
Example fix
// before
backend.readFile("/etc/hosts"); // outside virtual root
// after
Path root = Path.of("/srv/agent-data");
Path p = root.resolve("etc/hosts").normalize();
if (!p.startsWith(root)) throw new IllegalArgumentException("outside root");
backend.readFile(root.relativize(p).toString()); Defensive patterns
Strategy: validation
Validate before calling
Path root = backendRoot;
Path p = root.resolve(key).normalize();
if (!p.startsWith(root)) {
throw new IllegalArgumentException("Resolved path outside root: " + p);
} Type guard
boolean isInsideRoot(String key, Path root) {
return root.resolve(key).normalize().startsWith(root);
} Try / catch
try {
backend.readFile(key);
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Path:")) {
log.error("Key escaped virtual root {}", e.getMessage());
}
throw e;
} Prevention
- Configure the virtual root (cwd) wide enough for all legitimate operations.
- Convert external absolute paths into root-relative keys before calling the backend.
- Test join-and-normalize logic with adversarial inputs in CI.
- Avoid storing absolute external paths as backend keys.
When it happens
Trigger: resolvePath() (via dirPath/resolvedPath/searchPath/grepRaw) with a key whose normalized absolute form falls outside the configured virtual root directory.
Common situations: Configuring a cwd narrower than the paths the application actually needs; joining user input with the root such that the combined path points elsewhere; storing absolute external paths as keys.
Understand the failure class
Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.
Related errors
- Path outside root directory:
- Path traversal not allowed
- Path: outside root directory:
- Invalid encoded Argon2-hash
- Amount of performance parameters invalid
AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09).
Data as JSON: /api/errors/e8548298abe9fdfe.
Report an issue: GitHub.