astrid-runtime/astrid · error
process path {} overlaps a sensitive runtime path
Error message
process path {} overlaps a sensitive runtime path What it means
wrap_with_process_paths checks every granted read/write path against the built-in sensitive runtime masks (resolved from AstridHome). Grants that overlap a built-in mask are rejected with PermissionDenied — except a grant that is strictly inside the user's home root, which is explicitly allowed.
Source
Thrown at crates/astrid-workspace/src/sandbox/mod.rs:356
bwrap.arg("--ro-bind").arg(&inj.source).arg(&inj.target);
}
// #856 read-hole fix: the `--ro-bind / /` above mounts the entire
// host filesystem read-only, which exposed Astrid's secret/key/state
// dirs and the operator's home credential stores to the spawned
// process. Shadow each masked path so the agent reads nothing (see
// `push_mask_arg`). Placed AFTER the root ro-bind (so it overlays)
// and the worktree/injection binds; `run/` (socket+token) and `etc/`
// stay reachable for daemon access. Fail-secure: refuse the spawn if
// the home is unresolvable.
let built_in_masks = Self::masked_paths()?;
let home_root = astrid_core::dirs::AstridHome::resolve()?.home_dir();
for granted in extra_read_paths.iter().chain(extra_write_paths) {
if built_in_masks.iter().any(|masked| {
paths_overlap(granted, masked)
&& !(masked == &home_root && granted.starts_with(masked))
}) {
return Err(io::Error::new(
io::ErrorKind::PermissionDenied,
format!(
"process path {} overlaps a sensitive runtime path",
granted.display()
),
));
}
}
for masked in &built_in_masks {
Self::push_mask_arg(&mut bwrap, masked);
}
// Caller-supplied masks (the CoW upper/work dirs). Same mechanism,
// placed after the worktree/injection binds so they overlay; the
// CoW dirs live OUTSIDE the worktree, so no writable bind needs to
// punch back through. Existence is validated up front (a missing mask
// already failed the spawn), so every entry is masked unconditionally.
for masked in extra_masks {View on GitHub (pinned to affd8760f4)
Solutions
- Move the grant to a subpath under home_root so the allowed exception applies
- Narrow the granted path to exclude the sensitive runtime directory
- Canonicalize the grant and re-check overlap; a trailing-slash or .. component can make it envelope the mask
- Relocate the workspace/process data outside the sensitive runtime tree
Example fix
// before
read_paths.push(home.join(".astrid")); // is the sensitive runtime root itself
// after
read_paths.push(home.join("projects")); // strictly beneath home_root Defensive patterns
Strategy: validation
Validate before calling
let home = astrid_core::dirs::AstridHome::resolve()?.home_dir();
if !granted.starts_with(&home) {
panic!("grant {} must live under AstridHome", granted.display());
} Type guard
fn under_home(p: &Path, home: &Path) -> bool {
p.starts_with(home)
} Try / catch
match wrap_with_process_paths(...) {
Err(e) if e.to_string().contains("sensitive runtime path") =>
eprintln!("move grant under home or off the runtime path: {e}"),
other => other?,
} Prevention
- Always derive process grants from the resolved AstridHome root, not absolute guesses
- Re-validate grants after any AstridHome relocation
- Document which runtime directories are off-limits to grants
When it happens
Trigger: Calling wrap_with_process_paths with extra_read_paths/extra_write_paths entries that overlap built-in masks such as the AstridHome runtime directories (and are not home_root-relative), or that equal the home root without starting beneath it as a proper subpath.
Common situations: Pointing a process grant at the AstridHome config/state directory directly; granting a parent directory (e.g. $HOME or /etc) that envelopes a sensitive runtime path; after relocating AstridHome so an old grant now collides with the new runtime location.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- process path {} overlaps a copy-on-write mask
- DNS resolved to an unauthorized private or local IP address
- sandbox {label} contains forbidden characters (double-quote,
- workspace CoW mask path does not exist: {} — refusing to spa
- manifest exceeds its installed capability approval: {details
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/9113d348b53a1e14.
Report an issue: GitHub.