Graphify-Labs/graphify · error · ValueError
Path {path!r} escapes the allowed directory {base}. Only pat
Error message
Path {path!r} escapes the allowed directory {base}. Only paths inside graphify-out/ are permitted. What it means
Raised by the graph-path validator in graphify/security.py when the resolved absolute path of a requested graph file does not lie under the allowed graphify-out/ base directory (resolved.relative_to(base) fails). It is a path-traversal guard: only files inside the graph output directory may be loaded through this API.
Source
Thrown at graphify/security.py:346
for candidate in [resolved_hint, *resolved_hint.parents]:
if candidate.name == GRAPHIFY_OUT_NAME:
base = candidate
break
if base is None:
base = Path(GRAPHIFY_OUT).resolve()
base = base.resolve()
if not base.exists():
raise ValueError(
f"Graph base directory does not exist: {base}. "
"Run /graphify first to build the graph."
)
resolved = Path(path).resolve()
try:
resolved.relative_to(base)
except ValueError:
raise ValueError(
f"Path {path!r} escapes the allowed directory {base}. "
"Only paths inside graphify-out/ are permitted."
)
if not resolved.exists():
raise FileNotFoundError(f"Graph file not found: {resolved}")
return resolved
def check_graph_file_size_cap(path: Path) -> None:
"""Reject *path* if its size exceeds the configured graph-file cap.
Protects callers from memory bombs by failing fast before a multi-GiB
graph.json is read into memory and JSON-parsed. Silently returns when
``path.stat()`` cannot be read — the caller's own existence/path check
is expected to surface a clearer error in that case.
View on GitHub (pinned to 7fe58b0b0f)
Solutions
- Only request files that actually live under the graphify-out/ base directory.
- Construct paths with (base / relative_name) instead of concatenating strings, so traversal cannot occur.
- Remove or retarget symlinks inside graphify-out/ that resolve outside the base.
- If you are a server operator seeing this from clients, treat it as a malformed request, not something to work around.
Example fix
# before
p = resolve_graph_path("graphify-out/../../secrets/config.json")
# after: stay inside the base
p = resolve_graph_path("graphify-out/wiki/index.md") Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
def safe_graph_path(base: Path, rel: str | Path) -> Path:
"""Compose base + rel and verify containment before calling the library."""
candidate = (base / rel).resolve()
if base.resolve() not in candidate.parents and candidate != base.resolve():
raise ValueError(f"{rel!r} escapes {base}")
return candidate Type guard
def is_within_base(path: str | Path, base: Path) -> bool:
try:
Path(path).resolve().relative_to(base.resolve())
return True
except ValueError:
return False Try / catch
try:
p = resolve_graph_path(user_path)
except ValueError as e:
if "escapes the allowed directory" in str(e):
# client-supplied path — reject, never broaden
return error_response("path outside graphify-out")
raise Prevention
- Build paths with Path(base) / relative_part, never string concatenation.
- Reject or normalize '../' segments in any client-supplied path.
- Audit symlinks under graphify-out/ so resolve() stays inside the base.
When it happens
Trigger: Passing a path containing ../ sequences that escape graphify-out/, an absolute path pointing elsewhere on disk (/etc/passwd style probes), or a symlink inside graphify-out whose target resolves outside the base (Path.resolve() follows symlinks before the check).
Common situations: MCP client or tool consumer sends a project_path/file path outside the graph directory; scripts accidentally passing the repo root or a source file instead of the graph JSON; symlinks in graphify-out pointing at shared storage outside the tree.
Related errors
- Graph base directory does not exist: {base}. Run /graphify f
- Graph file not found: {resolved}
- Graph file not found: {resolved}
- ingest: {exc}
- OLLAMA_BASE_URL points at a link-local/metadata address ({ho
AI-assisted analysis of Graphify-Labs/graphify@7fe58b0b0f (2026-08-14).
Data as JSON: /api/errors/87977ab8fbb779fb.
Report an issue: GitHub.