{"record":{"id":"d00cb70fd5d1ee77","repo":"jdx/mise","slug":"option-path-must-be-a-safe-relative-path-n","errorCode":null,"errorMessage":"{option}: '{path}' must be a safe relative path (no absolute paths or parent directories)","messagePattern":"(.+?): '(.+?)' must be a safe relative path \\(no absolute paths or parent directories\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/backend/static_helpers.rs","lineNumber":1210,"sourceCode":"\n/// Rejects `bin`/`rename_exe` names that are not plain file names (`../tool`,\n/// `/abs/tool`, `bin/tool`), which would otherwise be joined onto the install\n/// or search directory and place the binary outside it.\npub(crate) fn ensure_plain_bin_name(option: &str, name: &str) -> eyre::Result<()> {\n    if !file::is_plain_file_name(name) {\n        bail!(\n            \"{option}: '{name}' must be a plain file name \\\n             (no path separators or parent directories)\"\n        );\n    }\n    Ok(())\n}\n\n/// Rejects a configured binary path that is absolute or contains parent\n/// components, while preserving the established `bin = \"bin/tool\"` form.\npub(crate) fn ensure_safe_relative_bin_path(option: &str, path: &str) -> eyre::Result<()> {\n    if !file::is_safe_relative_path(path) {\n        bail!(\n            \"{option}: '{path}' must be a safe relative path \\\n             (no absolute paths or parent directories)\"\n        );\n    }\n    Ok(())\n}\n\n/// Renames `path` (named `file_name`) to `target` within `dir`, preserving any\n/// required extension and ensuring the result is executable. A collision on the\n/// target (two mappings pointing at the same name, or the archive already\n/// containing that name) is unsatisfiable, so it fails the install loudly rather\n/// than silently dropping a binary and reporting success.\nfn finish_rename(dir: &Path, path: &Path, file_name: &str, target: &str) -> eyre::Result<()> {\n    let target_path = keep_required_extensions(dir, file_name, target, dir.join(target));\n    // Ensure the binary is executable whether or not we move it: ZIP archives drop\n    // the exec bit, and the file may already carry the desired name.\n    if !file::is_executable(path) {\n        file::make_executable(path)?;","sourceCodeStart":1192,"sourceCodeEnd":1228,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/backend/static_helpers.rs#L1192-L1228","documentation":"mise rejects configured binary paths that are absolute or contain parent-directory components. Unlike the plain-name check, safe relative paths like \"bin/tool\" are still allowed. ensure_safe_relative_bin_path prevents a config from escaping the install directory via an absolute path or '..'.","triggerScenarios":"Passing an absolute path ('/usr/bin/tool') or a path with '..' ('../tool', 'a/../../tool') to dest_filename, install_artifact, make_configured_bin_executable, or rename_executable_in_dir via a path-like config option.","commonSituations":"Users copying absolute paths from their own filesystem into tool config; nested relative paths that accidentally traverse upward after a config refactor.","solutions":["Rewrite the value as a path relative to the install directory without '..' components (e.g. 'bin/tool')","Remove any leading '/' or drive letter","Re-check after templating; ensure templates resolve to relative paths"],"exampleFix":"// before\nensure_safe_relative_bin_path(\"bin\", \"/opt/tools/bin/mytool\")?;\n// after\nensure_safe_relative_bin_path(\"bin\", \"bin/mytool\")?;","handlingStrategy":"validation","validationCode":"use std::path::{Path, Component};\nfn assert_safe_relative(path: &str) -> Result<(), String> {\n    let p = Path::new(path);\n    if p.is_absolute() || p.components().any(|c| c == Component::ParentDir) {\n        return Err(format!(\"unsafe relative path: {path}\"));\n    }\n    Ok(())\n}","typeGuard":"fn is_safe_relative(path: &str) -> bool {\n    !path.starts_with('/') && !Path::new(path).components().any(|c| c == std::path::Component::ParentDir)\n}","tryCatchPattern":null,"preventionTips":["Express all binary paths relative to the install dir","Reject absolute paths in config review","Avoid '..' components entirely"],"tags":["validation","path-safety","config"],"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"}