xai-org/grok-build · warning
path {:?} is outside the memory directory {:?}
Error message
path {:?} is outside the memory directory {:?} What it means
MemoryStorage::read_file canonicalizes the requested path and requires it to be inside the canonicalized global memory directory; otherwise it returns this PermissionDenied io::Error. It is a deliberate path-traversal guard so callers cannot read arbitrary files outside memory storage.
Source
Thrown at crates/codegen/xai-grok-memory/src/storage.rs:278
/// Both the path and the memory root must be canonicalizable; if either fails, the read is rejected.
pub fn read_file(
&self,
path: &Path,
from: Option<usize>,
lines: Option<usize>,
) -> std::io::Result<String> {
// Security: canonicalize both sides; fail hard if either doesn't exist
let canonical = dunce::canonicalize(path)?;
let canonical_global = dunce::canonicalize(&self.global_dir).map_err(|e| {
std::io::Error::new(
std::io::ErrorKind::NotFound,
format!("memory directory {:?} does not exist: {e}", self.global_dir),
)
})?;
// Fail-closed caveat for paths longer than MAX_PATH: see workspace clippy.toml
if !canonical.starts_with(&canonical_global) {
return Err(std::io::Error::new(
std::io::ErrorKind::PermissionDenied,
format!(
"path {:?} is outside the memory directory {:?}",
path, self.global_dir
),
));
}
// Read the canonicalized path, not the original, to prevent TOCTOU races.
let content = std::fs::read_to_string(&canonical)?;
let from = from.unwrap_or(0);
match lines {
Some(count) => {
let selected: Vec<&str> = content.lines().skip(from).take(count).collect();
Ok(selected.join("\n"))
}
None if from > 0 => {View on GitHub (pinned to bc7f02eddd)
Solutions
- Resolve the requested file relative to the memory directory root and pass a path inside it
- Reject/clean ../ segments and canonicalize user input before calling read_file
- Remove or re-point symlinks that escape the memory directory
- If access outside is intended, configure a different storage root that contains the target
Example fix
// before let p = std::path::PathBuf::from(user_supplied); // may be ../../etc/passwd let s = storage.read_file(&p, None, None)?; // after let p = memory_root.join(user_supplied); let p = dunce::canonicalize(&p)?; assert!(p.starts_with(&memory_root)); let s = storage.read_file(&p, None, None)?;
Defensive patterns
Strategy: validation
Validate before calling
fn is_inside_memory_dir(path: &Path, root: &Path) -> std::io::Result<bool> {
let c = dunce::canonicalize(path)?;
let r = dunce::canonicalize(root)?;
Ok(c.starts_with(r))
} Type guard
fn safe_memory_path(path: &Path, root: &Path) -> Option<PathBuf> {
let c = dunce::canonicalize(path).ok()?;
let r = dunce::canonicalize(root).ok()?;
if c.starts_with(r) { Some(c) } else { None }
} Try / catch
match storage.read_file(&path, None, None) {
Err(e) if e.kind() == std::io::ErrorKind::PermissionDenied => {
eprintln!("refusing path outside memory dir: {path:?}");
}
other => other?,
} Prevention
- Never pass raw user/LLM-supplied paths; join them onto the memory root
- Strip ../ components and canonicalize before calling
- Avoid symlinks inside the memory dir that escape the root
- Unit-test traversal attempts like test_storage_read_file_rejects_outside_path
When it happens
Trigger: Calling read_file with a path containing ../ escapes, a symlink resolving outside the memory root, an absolute path to another location, or a path inside a different profile directory.
Common situations: Constructing file names from user or LLM-supplied input without sanitization; symlinked memory directories; tests asserting rejection (test_storage_read_file_rejects_outside_path).
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
- journal is not a regular file: {}
- Failed to set working directory to {:?}: {}
- failed to read {}: {e}
- failed to write {}: {e}
- failed to create chrome trace {:?}: {}
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/606cd2f9df8d5df1.
Report an issue: GitHub.