{"record":{"id":"2b934f2204c7668c","repo":"jdx/mise","slug":"install-mise-must-not-contain-path","errorCode":null,"errorMessage":"install_mise must not contain '..': {path:?}","messagePattern":"install_mise must not contain '\\.\\.': (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/remote.rs","lineNumber":2220,"sourceCode":"\nfn validated_absolute_remote_path_output(output: &str, kind: &str) -> Result<String> {\n    let path = output.strip_suffix('\\n').unwrap_or(output);\n    if !path.starts_with('/') || path.contains(['\\0', '\\n', '\\r']) {\n        bail!(\"{kind} returned an unsafe absolute path: {path:?}\");\n    }\n    Ok(path.to_string())\n}\n\nfn validate_install_mise_path(path: &str) -> Result<()> {\n    validate_value(\"mise install path\", path)?;\n    if path.contains(['\\n', '\\r']) {\n        bail!(\"install_mise must not contain a newline: {path:?}\");\n    }\n    if !path.starts_with('/') && !path.starts_with(\"~/\") {\n        bail!(\"install_mise must be an absolute path or start with ~/: {path:?}\");\n    }\n    if path.split('/').any(|component| component == \"..\") {\n        bail!(\"install_mise must not contain '..': {path:?}\");\n    }\n    if matches!(\n        path.rsplit('/').next(),\n        None | Some(\"\") | Some(\".\") | Some(\"~\")\n    ) {\n        bail!(\"install_mise must name an executable file: {path:?}\");\n    }\n    Ok(())\n}\n\nfn validate_remote_executable(command: &str) -> Result<()> {\n    validate_value(\"mise command\", command)?;\n    let is_path = command.contains('/');\n    if command.starts_with('-')\n        || command.contains(['\\n', '\\r'])\n        || (!is_path && command.chars().any(char::is_whitespace))\n    {\n        bail!(\"remote mise command must be an executable name or path: {command:?}\");","sourceCodeStart":2202,"sourceCodeEnd":2238,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/remote.rs#L2202-L2238","documentation":"The remote install_mise path must not contain any '..' path component. This prevents path-traversal style tricks where the configured install location could escape the intended directory or be crafted to point outside expected locations on the remote host.","triggerScenarios":"Configuring install_mise with a value containing a '..' segment, e.g. \"/opt/../etc/mise\" or \"~/../root/mise\" — often from string concatenation or resolving symlinks textually.","commonSituations":"Building the path by joining user input; normalizing paths by hand; copying paths with redundant '..' segments from documentation.","solutions":["Remove '..' segments; write the canonical absolute path directly","Use the resolved real path of the binary on the remote host","Rebuild path construction so components are joined without traversal"],"exampleFix":"// before\ninstall_mise = \"/opt/../usr/local/bin/mise\"\n// after\ninstall_mise = \"/usr/local/bin/mise\"","handlingStrategy":"validation","validationCode":"const noTraversal = (p) => { if (typeof p !== 'string') return false; return !p.split('/').includes('..'); };","typeGuard":"const hasNoDotDotSegments = (s) => typeof s === 'string' && !s.split('/').includes('..');","tryCatchPattern":"try { setInstallMisePath(p); } catch (e) { p = path.posix.normalize(p); if (!hasNoDotDotSegments(p)) throw e; setInstallMisePath(p); }","preventionTips":["Normalize paths before writing them into config","Avoid building install paths via string concatenation of user input","Use realpath output (minus symlink hops you intend) as the configured value"],"tags":["config","path-validation","path-traversal"],"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"}