hashicorp/nomad · error
path escapes the alloc directory
Error message
path escapes the alloc directory
What it means
sanitizePath() enforces containment: escapingfs.ChildEscapesParentDir verifies the requested path stays within the resolved alloc directory. A path that escapes (e.g. via "..") returns the fixed error "path escapes the alloc directory" — a security guard against arbitrary file access.
Source
Thrown at client/allocdir/alloc_dir.go:427
// sanitizePath checks that the path does not escape the alloc directory,
// does not read into the secrets or private directories and returns an absolute
// path of the provided path.
func (a *AllocDir) sanitizePath(path string) (string, error) {
// In some non linux systmes, directories like /var and /tmp resolve to
// /private/var and /private/tmp.
resolvedAllocDir, err := filepath.EvalSymlinks(a.AllocDir)
if err != nil {
return "", fmt.Errorf("failed to resolve alloc directory: %w", err)
}
requestedPath, err := filepath.Abs(filepath.Join(resolvedAllocDir, path))
if err != nil {
return "", fmt.Errorf("failed to resolve requested path: %w", err)
}
if err := escapingfs.ChildEscapesParentDir(resolvedAllocDir, requestedPath); err != nil {
return "", fmt.Errorf("path escapes the alloc directory")
}
a.mu.RLock()
defer a.mu.RUnlock()
// Check it does not access the secrets or private directories
for _, taskDir := range a.TaskDirs {
rps := strings.ReplaceAll(requestedPath, "/Secrets", "/secrets")
if err := escapingfs.ChildEscapesParentDir(taskDir.SecretsDir, rps); err == nil {
return "", fmt.Errorf("Reading secret file prohibited: %s", path)
}
rpp := strings.ReplaceAll(requestedPath, "/Private", "/private")
if err := escapingfs.ChildEscapesParentDir(taskDir.PrivateDir, rpp); err == nil {
return "", fmt.Errorf("Reading secret file prohibited: %s", path)
}
}
View on GitHub (pinned to 482b49bf1a)
Solutions
- Use paths relative to the alloc dir and never start with / or contain .. that exits it
- Use task-local dirs (NOMAD_ALLOC_DIR env, task dir) for file access
- Remove or fix symlinks inside the alloc dir that point outside
- Validate user-supplied paths in tooling built on the Nomad filesystem API
Example fix
// before
allocDir.ReadAt("../../../../etc/passwd", 0)
// after
allocDir.ReadAt("task/mytask/out.txt", 0) Defensive patterns
Strategy: validation
Validate before calling
func safeRel(base, p string) error {
abs, err := filepath.Abs(filepath.Join(base, p))
if err != nil { return err }
rel, err := filepath.Rel(base, abs)
if err != nil { return err }
if rel == ".." || strings.HasPrefix(rel, ".."+string(os.PathSeparator)) {
return fmt.Errorf("path escapes base")
}
return nil
} Try / catch
f, err := allocDir.ReadAt(relPath, 0)
if err != nil && strings.Contains(err.Error(), "path escapes the alloc directory") {
return ErrPathTraversalRejected // do not retry; reject the request
} Prevention
- Never pass absolute or ..-containing paths to the alloc file API
- Use NOMAD_ALLOC_DIR / task-dir-relative paths
- Avoid symlinks that point outside the alloc dir
- Treat this error as a request bug or probe, and reject without retry
When it happens
Trigger: Calling List/Stat/ReadAt/BlockUntilExists/ChangeEvents with a relative path containing enough ".." components to resolve outside the alloc dir, or a path that follows a symlink out of it.
Common situations: Misbehaving or malicious task/artifact config referencing paths like ../../etc/passwd; templates or filesystem APIs given host paths instead of alloc-relative paths.
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
- file path escapes capture directory
- file path %q escapes capture directory %q
- Reading secret file prohibited: %s
- archive contains object that escapes alloc dir
- archive contains symlink that escapes alloc dir
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/f37d5930ed148b56.
Report an issue: GitHub.