{"record":{"id":"87fd0ba3bb6364bd","repo":"jdx/mise","slug":"unsafe-source-repository-path","errorCode":null,"errorMessage":"unsafe source repository path","messagePattern":"unsafe source repository path","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src/system/remote_repository.rs","lineNumber":233,"sourceCode":"        .args([\"clone\", \"--no-checkout\", \"--\"])\n        .arg(bundle)\n        .arg(&checkout)\n        .output()?;\n    if !output.status.success() {\n        bail!(\"invalid transferred repository bundle\");\n    }\n    if git(&checkout, &[\"rev-parse\", \"HEAD\"])? != revision {\n        bail!(\"transferred revision mismatch\");\n    }\n    let entries = git(&checkout, &[\"ls-tree\", \"-r\", \"-z\", \"--name-only\", revision])?;\n    for entry in entries.split('\\0').filter(|s| !s.is_empty()) {\n        let path = Path::new(entry);\n        if path\n            .components()\n            .any(|c| !matches!(c, std::path::Component::Normal(_)))\n            || entry.split('/').any(|p| p.eq_ignore_ascii_case(\".git\"))\n        {\n            bail!(\"unsafe source repository path\");\n        }\n        if entry.to_ascii_lowercase().ends_with(\".local.toml\") {\n            bail!(\n                \"source contains machine-local configuration ({entry}); remove it from the repository before onboarding\"\n            );\n        }\n    }\n    git(&checkout, &[\"remote\", \"set-url\", \"origin\", origin])?;\n    let branch = git(&checkout, &[\"symbolic-ref\", \"--short\", \"HEAD\"])?;\n    git(\n        &checkout,\n        &[\"-c\", \"core.hooksPath=/dev/null\", \"checkout\", &branch],\n    )?;\n    if destination.join(\".git\").exists() {\n        if git(destination, &[\"remote\", \"get-url\", \"origin\"])? != origin {\n            bail!(\"global configuration origin does not match\");\n        }\n        if !git(","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/remote_repository.rs#L215-L251","documentation":"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.","triggerScenarios":"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`.","commonSituations":"Repos crafted (or accidently committed) with `..` filenames, submodule artifacts, or nested `.git` directories from vendored checkouts; security scanning of untrusted onboarding sources.","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."],"exampleFix":"// before (repo tree)\n.git/hooks/pre-commit\n../shared/config.toml\n// after — clean and republish\n$ git rm -r --cached .git/hooks  # and delete nested .git dirs, '..' files\n$ git commit -m \"remove unsafe paths\"\n$ git rev-parse HEAD  # use the new SHA for onboarding","handlingStrategy":"validation","validationCode":"function hasUnsafePath(entry: string): boolean {\n  const segs = entry.split(\"/\");\n  return segs.some(s => s === \"..\" || s === \".\" || s.length === 0 || s.toLowerCase() === \".git\")\n    || entry.startsWith(\"/\");\n}\n// audit the repo: git ls-tree -r --name-only <rev> | xargs -I{} check hasUnsafePath","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["security","path-traversal","git","validation"],"backgroundTag":"path-traversal-blocked","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}