NousResearch/hermes-agent · error · ValueError
path is outside the allowed workspace
Error message
path is outside the allowed workspace
What it means
A file reference (@file: path in a message) resolved to a path outside the allowed workspace root. The _resolve_path helper in agent/context_references.py expands the target (including ~), resolves symlinks, and requires the result to be relative to allowed_root when one is supplied. This is a workspace-containment guard for reference expansion, which the gateway feeds with untrusted remote message text.
Source
Thrown at agent/context_references.py:480
raw = await web_extract_tool([url], format="markdown")
payload = json.loads(raw)
docs = payload.get("results", [])
if not docs:
return ""
doc = docs[0]
return str(doc.get("content") or doc.get("raw_content") or "").strip()
def _resolve_path(cwd: Path, target: str, *, allowed_root: Path | None = None) -> Path:
path = Path(os.path.expanduser(target))
if not path.is_absolute():
path = cwd / path
resolved = path.resolve()
if allowed_root is not None:
try:
resolved.relative_to(allowed_root)
except ValueError as exc:
raise ValueError("path is outside the allowed workspace") from exc
return resolved
def _ensure_reference_path_allowed(path: Path) -> None:
from hermes_constants import get_hermes_home
home = Path(os.path.expanduser("~")).resolve()
hermes_home = get_hermes_home().resolve()
blocked_exact = {home / rel for rel in _SENSITIVE_HOME_FILES}
blocked_exact.add(hermes_home / ".env")
blocked_dirs = [home / rel for rel in _SENSITIVE_HOME_DIRS]
blocked_dirs.extend(hermes_home / rel for rel in _SENSITIVE_HERMES_DIRS)
if path in blocked_exact:
raise ValueError("path is a sensitive credential file and cannot be attached")
for blocked_dir in blocked_dirs:
try:View on GitHub (pinned to c896c09c42)
Solutions
- Reference only files inside the session's working directory / allowed workspace root.
- Copy the needed file into the workspace before attaching it.
- If the file legitimately lives elsewhere, adjust the session's working directory (terminal.cwd in config.yaml) so the allowed root covers it.
- Check for symlinks in the path (ls -l) — a symlink resolving outside the workspace triggers this even if the link itself is inside.
Example fix
# before — outside workspace @file:~/notes/secret-steps.md # after — copy into the workspace first, then reference cp ~/notes/secret-steps.md ./secret-steps.md @file:./secret-steps.md
Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
def is_within_workspace(target: str, allowed_root: Path) -> bool:
p = Path(os.path.expanduser(target))
if not p.is_absolute():
p = Path.cwd() / p
try:
p.resolve().relative_to(allowed_root.resolve())
return True
except ValueError:
return False Try / catch
try:
expand_references(message)
except ValueError as e:
if "outside the allowed workspace" in str(e):
# tell the user to move the file into the workspace
... Prevention
- Keep referenced files inside the session working directory
- Check for symlinks escaping the workspace before referencing
- Set terminal.cwd to a root that contains everything you will attach
When it happens
Trigger: A message containing @file:../../etc/passwd or @file:/etc/hosts when the allowed_root is the session cwd; a symlink inside the workspace that resolves outside it (Path.resolve() follows symlinks); an absolute path to any location outside the workspace root.
Common situations: Attempting to attach system files or home-directory files via @file: references in a workspace-scoped session (CLI or gateway); symlinked project directories pointing outside the workspace; remote chat peers probing with absolute paths.
Related errors
- path is a sensitive credential file and cannot be attached
- path is a sensitive credential or internal Hermes path and c
- path could not be verified against the credential deny-list
- Path '{resolved}' is outside the session cwd '{root}'.
- ${label} exited and ${dashboardIndexUrl(baseUrl)} is served
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/0e909f8587ce3910.
Report an issue: GitHub.