astrid-runtime/astrid · error · std::io::Error::InvalidInput

{var_name} must not contain '..' path components

Error message

{var_name} must not contain '..' path components

What it means

Thrown by reject_parent_traversal when a path configured via an environment variable contains '..' parent-directory components. This blocks path-traversal attacks and accidental escapes from the intended Astrid home directory.

Source

Thrown at crates/astrid-core/src/dirs.rs:228

    #[error("workspace state directory name must not contain path separators")]
    Separator,
    /// The name contains a non-portable character.
    #[error(
        "workspace state directory name may contain only ASCII letters, digits, '.', '_', and '-'"
    )]
    InvalidCharacter,
    /// The name exceeds the portable length bound.
    #[error("workspace state directory name must be at most 64 bytes")]
    TooLong,
    /// The name is reserved by a supported filesystem.
    #[error("workspace state directory name is reserved: {0:?}")]
    Reserved(String),
}

/// Reject paths containing `..` (parent directory) components.
fn reject_parent_traversal(path: &Path, var_name: &str) -> io::Result<()> {
    if path.components().any(|c| matches!(c, Component::ParentDir)) {
        return Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            format!("{var_name} must not contain '..' path components"),
        ));
    }
    Ok(())
}

// ── AstridHome (system-level) ────────────────────────────────────────────

/// Global Astrid home directory (`~/.astrid/`, Windows `LocalAppData`, or
/// `$ASTRID_HOME`).
///
/// FHS-aligned system layout with config (`etc/`), persistent state (`var/`),
/// runtime (`run/`), logs (`log/`), keys (`keys/`), and shared modules (`lib/`).
/// Principal content is authoritative in `AstridFilesystem`; native `home/` is
/// retained only as a legacy migration source.
#[derive(Debug, Clone)]
pub struct AstridHome {

View on GitHub (pinned to affd8760f4)

Solutions

  1. Remove '..' segments from the ASTRID_HOME value and use a clean absolute path
  2. Re-export ASTRID_HOME with a canonicalized path (e.g. via realpath)

Example fix

// before
export ASTRID_HOME=/home/user/.astrid/../shared
// after
export ASTRID_HOME=/home/user/shared
Defensive patterns

Strategy: validation

Validate before calling

fn is_safe(p: &str) -> bool {
    let pb = std::path::PathBuf::from(p);
    pb.is_absolute() && !pb.components().any(|c| matches!(c, std::path::Component::ParentDir))
}
assert!(is_safe(&astrid_home));

Type guard

fn safe_env_path(v: &str) -> Option<std::path::PathBuf> {
    let p = std::path::PathBuf::from(v);
    (p.is_absolute()
        && !p.components().any(|c| matches!(c, std::path::Component::ParentDir)))
    .then_some(p)
}

Try / catch

match result {
    Err(e) if e.kind() == io::ErrorKind::InvalidInput && e.to_string().contains("'..'") => {
        eprintln!("Fix the env var: remove '..' components");
    },
    other => other?,
}

Prevention

When it happens

Trigger: Calling resolve_with_env with ASTRID_HOME (or HOME) set to a value like '/home/user/.astrid/../evil' or '~/..'; reject_parent_traversal scans Path components for Component::ParentDir.

Common situations: Shell config exporting a relative or dot-dot-containing ASTRID_HOME, copy-pasted paths with '..' segments, or malicious environment in untrusted contexts.

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


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/f6330927303799ad. Report an issue: GitHub.