hashicorp/nomad · error
Reading secret file prohibited: %s
Error message
Reading secret file prohibited: %s
What it means
sanitizePath() additionally blocks access to any task's SecretsDir. If the requested path resolves inside a SecretsDir, this error is returned (checked case-insensitively by replacing /Secrets with /secrets). This protects Task Role Credentials/vault secrets from the file API.
Source
Thrown at client/allocdir/alloc_dir.go:437
}
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)
}
}
return requestedPath, nil
}
// Stat returns information about the file at a path relative to the alloc dir
func (a *AllocDir) Stat(path string) (*cstructs.AllocFileInfo, error) {
sanitizedPath, err := a.sanitizePath(path)
if err != nil {
return nil, err
}View on GitHub (pinned to 482b49bf1a)
Solutions
- Do not access the secrets dir via the alloc filesystem API; use the secret's intended delivery mechanism (template, env, vault integration)
- Move application config that must be readable out of the secrets dir into a normal task dir path
- If legitimate access is needed, read the file inside the task process itself rather than via AllocDir APIs
Example fix
// before
allocDir.ReadAt("task/web/secrets/token", 0)
// after
// read inside the task, e.g. via exec or template delivery, not the file API Defensive patterns
Strategy: validation
Validate before calling
if strings.Contains(strings.ToLower(relPath), "secrets") {
return fmt.Errorf("refusing to access secrets dir")
} Try / catch
data, err := allocDir.ReadAt(relPath, 0)
if err != nil && strings.Contains(err.Error(), "Reading secret file prohibited") {
return ErrSecretsAccessDenied // request is not permitted by design
} Prevention
- Never read secrets via the alloc file API; use templates/env/vault delivery
- Exclude secrets dir from debug snapshots and file walkers
- Educate tooling that the secrets dir is intentionally unreadable
When it happens
Trigger: Calling List/Stat/ReadAt/BlockUntilExists/ChangeEvents with a path resolving inside a task's secrets directory (e.g. secrets/token or .../Secrets/...).
Common situations: Templates or tooling trying to read the vault-derived secret token file; filesystem snapshot/debug tooling enumerating all task files including secrets; user asking the API for secrets dir contents.
Related errors
- path escapes the alloc directory
- archive contains object that escapes alloc dir
- archive contains symlink that escapes alloc dir
- file path escapes capture directory
- file path %q escapes capture directory %q
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/6d46d0a345661995.
Report an issue: GitHub.