{"record":{"id":"646f235d128df753","repo":"jdx/mise","slug":"refusing-to-resolve-managed-directory-to-the-fi","errorCode":null,"errorMessage":"refusing to resolve managed directory {} to the filesystem root","messagePattern":"refusing to resolve managed directory (.+?) to the filesystem root","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src/system/managed_files.rs","lineNumber":1626,"sourceCode":"                    SFlag::from_bits_truncate(metadata.st_mode).contains(SFlag::S_IFLNK)\n                }) {\n                    let parent = fstat(&directory)?;\n                    if parent.st_uid != 0 || parent.st_mode & 0o022 != 0 {\n                        bail!(\n                            \"refusing to follow symlink {} from an untrusted parent directory\",\n                            component_path.display()\n                        );\n                    }\n                    let target = nix::fcntl::readlinkat(&directory, name.as_os_str())?;\n                    let mut resolved = if Path::new(&target).is_absolute() {\n                        PathBuf::from(target)\n                    } else {\n                        current.join(target)\n                    };\n                    resolved.extend(components.iter().skip(index + 1));\n                    let resolved = resolved.absolutize()?.to_path_buf();\n                    if resolved == Path::new(\"/\") {\n                        bail!(\n                            \"refusing to resolve managed directory {} to the filesystem root\",\n                            path.display()\n                        );\n                    }\n                    return open_or_create_directory_tree_inner(&resolved, followed_symlinks + 1);\n                }\n                if open_error != nix::errno::Errno::ENOENT {\n                    return Err(open_error).wrap_err_with(|| {\n                        format!(\n                            \"failed to open path component {} without following symlinks\",\n                            component_path.display()\n                        )\n                    });\n                }\n                let created_by_us = match mkdirat(\n                    &directory,\n                    name.as_os_str(),\n                    Mode::from_bits_truncate(0o777),","sourceCodeStart":1608,"sourceCodeEnd":1644,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/managed_files.rs#L1608-L1644","documentation":"When a symlink in the managed path is followed, the library re-resolves the remaining path and refuses if the result is the filesystem root `/`. Resolving a managed directory to `/` would make the library operate on the root directory, which is never intended and extremely destructive. This is a hard safety invariant in the symlink-following logic.","triggerScenarios":"A symlink component whose target (after absolutize and appending remaining components) equals `/` — e.g. a symlink `tools -> /` or a chain of symlinks that ultimately resolves to `/`.","commonSituations":"A malicious or mistaken symlink pointing at `/`; careless link farms where a symlink chain (link -> link2 -> /) collapses to the root; cleanup scripts that repointed symlinks incorrectly.","solutions":["Remove or fix the symlink that resolves to `/` (`readlink -f <symlink>` to confirm)","Point the symlink at a specific subdirectory rather than the root","Recreate the managed directory structure from a clean state","Audit symlink chains with `namei -l <path>` before relinking"],"exampleFix":"// before\n$ ln -s / /opt/tools/root\n// after\n$ rm /opt/tools/root\n$ ln -s /opt/tools-v1 /opt/tools/root","handlingStrategy":"validation","validationCode":"fn resolves_to_root(path: &Path) -> std::io::Result<bool> {\n    let resolved = path.canonicalize()?;\n    Ok(resolved == std::path::Path::new(\"/\"))\n}","typeGuard":"fn not_root(path: &Path) -> bool {\n    std::fs::canonicalize(path).map(|p| p != std::path::Path::new(\"/\")).unwrap_or(true)\n}","tryCatchPattern":"match result {\n    Err(e) if e.to_string().contains(\"to the filesystem root\") => {\n        let target = std::fs::read_link(suspect_link(path))?;\n        remove_and_relink(target); // never point at /\n    }\n    Err(e) => return Err(e),\n    Ok(v) => v,\n}","preventionTips":["Never create symlinks whose target is /","Validate symlink targets with readlink -f before creating links","Run namei -l on link chains to check final resolution","Restrict who can write to directories containing managed symlinks"],"tags":["security","symlink","filesystem","safety-check"],"backgroundTag":"path-traversal-blocked","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}