{"record":{"id":"fd2ef5d8d3e0f6be","repo":"sxyazi/yazi","slug":"git-symlink-target-escapes-repository","errorCode":null,"errorMessage":"Git symlink target escapes repository: `{}`","messagePattern":"Git symlink target escapes repository: `(.+?)`","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"yazi-cli/src/package/git.rs","lineNumber":82,"sourceCode":"\n\t\t\tlet Some(tab) = ent.iter().position(|&b| b == b'\\t') else { continue };\n\t\t\tlet link = path.join(\n\t\t\t\tPath::from_wtf8(&ent[tab + 1..]).context(\"Git path cannot be represented by the OS\")?,\n\t\t\t);\n\n\t\t\tlet is_symlink = fs::symlink_metadata(&link).await?.file_type().is_symlink();\n\t\t\tlet original = if is_symlink {\n\t\t\t\tfs::read_link(&link).await? // TODO: compat for old caches, remove in the future\n\t\t\t} else {\n\t\t\t\tPathBuf::from_wtf8_vec(fs::read(&link).await?)\n\t\t\t\t\t.context(\"Git symlink origin cannot be represented by the OS\")?\n\t\t\t};\n\t\t\tlet original = fs::canonicalize(link.parent().unwrap_or(&path).join(original))\n\t\t\t\t.await\n\t\t\t\t.with_context(|| format!(\"failed to resolve Git symlink target `{}`\", link.display()))?;\n\n\t\t\tif !original.starts_with(&path) {\n\t\t\t\tbail!(\"Git symlink target escapes repository: `{}`\", link.display());\n\t\t\t} else if is_symlink {\n\t\t\t\tfs::remove_file(&link).await?;\n\t\t\t}\n\n\t\t\tfs::copy(original, &link)\n\t\t\t\t.await\n\t\t\t\t.with_context(|| format!(\"failed to materialize `{}`\", link.display()))?;\n\t\t}\n\n\t\tOk(())\n\t}\n\n\tasync fn exec(f: impl FnOnce(&mut Command) -> &mut Command) -> Result<()> {\n\t\tlet status = f(Command::new(\"git\").args([\n\t\t\t\"-c\",\n\t\t\t\"core.eol=lf\",\n\t\t\t\"-c\",\n\t\t\t\"core.autocrlf=false\",","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/sxyazi/yazi/blob/5f901b886b14de1f17460b6e52e9de5d67f8aba9/yazi-cli/src/package/git.rs#L64-L100","documentation":"Safety guard while materializing git symlinks: a symlink's canonicalized target resolved outside the repository root, which the package manager refuses to materialize to prevent a checkout from writing outside its own directory. The faulting input is the symlink target recorded in the repo (`original` after canonicalization).","triggerScenarios":"Thrown at yazi-cli/src/package/git.rs:82 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Audit the package's symlinks; fix or remove ones pointing outside the repository.","Report the offending package to its maintainer if it ships escaping symlinks.","Avoid installing packages with untrusted symlink content."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"5f901b886b14de1f17460b6e52e9de5d67f8aba9","analyzedAt":"2026-09-02T18:38:25.566Z","contentChangedAt":"2026-09-02T18:38:25.566Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}