jdx/mise · critical
unsafe source repository path
Error message
unsafe source repository path
What it means
install_at walks every path in the repository tree (`git ls-tree -r`) and rejects any entry containing non-Normal path components (absolute paths, `..`, `.`, drive/root prefixes) or any path segment named `.git` (case-insensitive). This blocks path-traversal and git-directory smuggling from a malicious or misconfigured source repository.
Solutions
- Find offending entries: `git ls-tree -r --name-only <rev> | grep -iE '(^|/)\.git(/|$)|\.\.|^/'` and remove them from the repository.
- Remove vendored nested .git directories before committing (use a subtree export or copy files without VCS metadata).
- Push a cleaned commit, then re-run onboarding with the new revision.
Example fix
// before (repo tree) .git/hooks/pre-commit ../shared/config.toml // after — clean and republish $ git rm -r --cached .git/hooks # and delete nested .git dirs, '..' files $ git commit -m "remove unsafe paths" $ git rev-parse HEAD # use the new SHA for onboarding
Defensive patterns
Strategy: validation
Validate before calling
function hasUnsafePath(entry: string): boolean {
const segs = entry.split("/");
return segs.some(s => s === ".." || s === "." || s.length === 0 || s.toLowerCase() === ".git")
|| entry.startsWith("/");
}
// audit the repo: git ls-tree -r --name-only <rev> | xargs -I{} check hasUnsafePath Prevention
- Audit source repos for `.git` dirs, `..` filenames, and absolute paths before onboarding.
- Add a CI check that fails on unsafe tree entries (ls-tree scan).
- Only onboard repositories you control or have reviewed.
- Exclude vendored VCS metadata when committing.
When it happens
Trigger: Installing from a source repository whose tree contains entries like `../../etc/passwd`, `/absolute/path`, `.git/hooks/x`, or a directory literally named `GIT` or `.Git`.
Common situations: Repos crafted (or accidently committed) with `..` filenames, submodule artifacts, or nested `.git` directories from vendored checkouts; security scanning of untrusted onboarding sources.
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
- brew-cask: invalid
- brew-cask: invalid structured flight path
- cask uses `# `, which mise's cask shim does not support
- invalid repository origin
- invalid tool ref : contains path-traversal sequence
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/87fd0ba3bb6364bd.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/remote_repository.rs:233
.args(["clone", "--no-checkout", "--"])
.arg(bundle)
.arg(&checkout)
.output()?;
if !output.status.success() {
bail!("invalid transferred repository bundle");
}
if git(&checkout, &["rev-parse", "HEAD"])? != revision {
bail!("transferred revision mismatch");
}
let entries = git(&checkout, &["ls-tree", "-r", "-z", "--name-only", revision])?;
for entry in entries.split('\0').filter(|s| !s.is_empty()) {
let path = Path::new(entry);
if path
.components()
.any(|c| !matches!(c, std::path::Component::Normal(_)))
|| entry.split('/').any(|p| p.eq_ignore_ascii_case(".git"))
{
bail!("unsafe source repository path");
}
if entry.to_ascii_lowercase().ends_with(".local.toml") {
bail!(
"source contains machine-local configuration ({entry}); remove it from the repository before onboarding"
);
}
}
git(&checkout, &["remote", "set-url", "origin", origin])?;
let branch = git(&checkout, &["symbolic-ref", "--short", "HEAD"])?;
git(
&checkout,
&["-c", "core.hooksPath=/dev/null", "checkout", &branch],
)?;
if destination.join(".git").exists() {
if git(destination, &["remote", "get-url", "origin"])? != origin {
bail!("global configuration origin does not match");
}
if !git(View on GitHub (pinned to 533346cc37)