astrid-runtime/astrid · error

git history path must be a relative in-repository path

Error message

git history path must be a relative in-repository path

What it means

`validate_relative_git_path` rejects paths that are not clean relative paths inside a repository: absolute paths, `.`/`..`/root/prefix components, or anything containing a colon are refused. This guards `git ls-tree` invocations against path traversal and argument injection.

Source

Thrown at crates/astrid-storage-chunker-evidence/src/corpus.rs:556

        bail!("corpus label must contain only lowercase ASCII letters, digits, and hyphens");
    }
    Ok(())
}

fn validate_relative_git_path(path: &Path) -> Result<()> {
    if path.as_os_str().is_empty()
        || path.is_absolute()
        || path.components().any(|component| {
            matches!(
                component,
                std::path::Component::ParentDir
                    | std::path::Component::RootDir
                    | std::path::Component::Prefix(_)
            )
        })
        || path.to_string_lossy().contains(':')
    {
        bail!("git history path must be a relative in-repository path");
    }
    Ok(())
}

fn git_path_exists_at_revision(
    repository: &Path,
    relative_path: &Path,
    revision: &str,
) -> Result<bool> {
    let tree = Command::new("git")
        .args(["-C"])
        .arg(repository)
        .args(["ls-tree", "--full-tree", revision, "--"])
        .arg(relative_path)
        .output()
        .context("inspect captured version path")?;
    if !tree.status.success() {
        bail!(

View on GitHub (pinned to affd8760f4)

Solutions

  1. Use a plain relative path inside the repository, e.g. `bench/corpus/sample.bin`
  2. Strip leading `/`, resolve/remove `..` components relative to the repo root before passing
  3. Remove any `:` characters from the path (or rename the offending file)

Example fix

// before
let spec = "samples=/srv/repo::/data/../../etc/passwd";
// after
let spec = "samples=/srv/repo::bench/corpus/sample.bin";
Defensive patterns

Strategy: validation

Validate before calling

fn is_safe_rel_path(p: &Path) -> bool {
    !p.as_os_str().is_empty()
        && !p.is_absolute()
        && p.components().all(|c| matches!(c, std::path::Component::Normal(_)))
        && !p.to_string_lossy().contains(':')
}
assert!(is_safe_rel_path(&rel), "unsafe git history path: {rel:?}");

Try / catch

match version_chain_from_git(&repo, &rev, &rel) {
    Ok(chain) => chain,
    Err(e) if e.to_string().contains("relative in-repository path") => {
        let cleaned = normalize_rel(&rel);
        version_chain_from_git(&repo, &rev, &cleaned)?
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Passing a `RELATIVE_PATH` (from a `--git-history NAME=REPO::PATH` spec) that is absolute, contains `..`, starts with `/` or a Windows drive prefix, or includes a `:` character into `version_chain_from_git`.

Common situations: Users supplying absolute paths in the git-history spec, copy-pasting `repo/sub/dir:file` notation, or attempting `../../etc/passwd` style traversal in the config.

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/5f939868197a403e. Report an issue: GitHub.