{"record":{"id":"5c98a22c79d7f3bb","repo":"jdx/mise","slug":"invalid-dependency-sidecar-path","errorCode":null,"errorMessage":"invalid dependency sidecar path {}","messagePattern":"invalid dependency sidecar path (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/lockfile/graph.rs","lineNumber":138,"sourceCode":"            return Ok(self.clone());\n        };\n        let text = std::fs::read_to_string(dir.join(T::GRAPH_FILE))\n            .map_err(|e| eyre!(\"dependency sidecar {}: {e}; run `mise lock`\", dir.display()))?;\n        let graph = T::read(dir, text)\n            .map_err(|e| eyre!(\"dependency sidecar {}: {e}; run `mise lock`\", dir.display()))?;\n        Ok(Self::Inline {\n            graph,\n            dir: Some(dir.clone()),\n            digest: OnceLock::new(),\n        })\n    }\n    pub(crate) fn resolve_path(&mut self, lockfile: &Path) -> Result<()> {\n        if let Self::Sidecar { dir, .. } = self {\n            if dir.is_absolute()\n                || dir.components().any(|c| !matches!(c, Component::Normal(_)))\n                || dir.to_string_lossy().contains('\\\\')\n            {\n                bail!(\"invalid dependency sidecar path {}\", dir.display());\n            }\n            *dir = absolute(lockfile.parent().unwrap_or(Path::new(\".\"))).join(&*dir);\n        }\n        Ok(())\n    }\n    pub(crate) fn parse(value: toml::Value) -> Result<Self> {\n        if value.get(\"path\").is_some() {\n            #[derive(Deserialize)]\n            #[serde(deny_unknown_fields)]\n            struct Pointer {\n                path: PathBuf,\n                digest: String,\n            }\n            let p: Pointer = value.try_into()?;\n            if !p\n                .digest\n                .strip_prefix(\"sha256:\")\n                .is_some_and(|s| s.len() == 64 && s.bytes().all(|b| b.is_ascii_hexdigit()))","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/lockfile/graph.rs#L120-L156","documentation":"Dependency sidecars record an external dependency graph per tool. `GraphRef::resolve_path` validates the sidecar's relative `dir`: it must be relative, contain only normal path components, and have no backslashes — otherwise the path could escape the tool directory or be non-portable. It then resolves the dir against the lockfile's parent directory.","triggerScenarios":"Loading a lockfile whose `[dependency]` sidecar entry has an absolute path, `..`/root/curdir components (e.g. `../shared/deps`), or Windows-style backslashes in `path`, then calling `resolve_path`.","commonSituations":"Hand-edited or generated-by-script lockfiles with absolute or traversal paths; lockfiles copied from Windows; tools writing sidecar paths computed on another OS.","solutions":["Fix the `path` in the lockfile's dependency sidecar entry to a relative path with only normal components (e.g. `deps/tool`)","Remove any `..`, absolute prefixes, or `\\` separators from the path","Regenerate the lockfile instead of hand-editing so the sidecar path is produced correctly","If the graph lives elsewhere, move the sidecar directory under the tool directory and reference it relatively"],"exampleFix":"# before (mise.lock)\npath = \"../shared/graph.toml\"\n# after\npath = \"shared/graph.toml\"","handlingStrategy":"validation","validationCode":"use std::path::{Component, Path};\nfn is_valid_sidecar_dir(dir: &Path) -> bool {\n    !dir.is_absolute()\n        && dir.components().all(|c| matches!(c, Component::Normal(_)))\n        && !dir.to_string_lossy().contains('\\\\')\n}","typeGuard":"fn valid_sidecar_dir(dir: &str) -> Option<&str> {\n    let p = Path::new(dir);\n    (!p.is_absolute()\n        && p.components().all(|c| matches!(c, Component::Normal(_)))\n        && !dir.contains('\\\\')).then_some(dir)\n}","tryCatchPattern":null,"preventionTips":["Never hand-edit sidecar paths in mise.lock; regenerate instead","Keep sidecar directories relative to the lockfile location","Normalize Windows-produced paths to forward slashes before committing","Reject `..` components when generating sidecar paths in scripts"],"tags":["lockfile","path","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"}