{"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":2222,"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":2204,"sourceCodeEnd":2240,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/remote.rs#L2204-L2240","documentation":"`validate_install_mise_path` rejects any `install_mise` value containing a '..' path component. Parent-directory traversal in a remotely executed path can escape the intended install directory and is a command-injection/safety hazard, so mise blocks it outright.","triggerScenarios":"install_mise contains '/..' or ends with '..' e.g. '/opt/../bin/mise' or '~/mise/..' — typically from templated paths or variables that interpolate to '..'.","commonSituations":"Config templates concatenating variables that yield '..'; typos like '/usr/local/bin/../mise'; attempting path tricks in shared config files.","solutions":["Rewrite the path without '..' components (normalize it yourself to the final absolute path)","Fix the templating/variable interpolation that injects '..' into the value","Verify the config file was not tampered with if '..' appears unexpectedly"],"exampleFix":"// before\ninstall_mise = \"/opt/../usr/local/bin/mise\"\n// after\ninstall_mise = '/usr/local/bin/mise'","handlingStrategy":"validation","validationCode":"if (p.split('/').includes('..')) throw new Error('install_mise must not contain ..');","typeGuard":"const hasNoDotDot = (s: unknown): s is string =>\n  typeof s === 'string' && !s.split('/').includes('..');","tryCatchPattern":"try { validate_install_mise_path(p)?; } catch (e) {\n  if (String(e).includes(\"'..'\")) { /* normalize the path and retry */ }\n}","preventionTips":["Normalize templated paths before writing them to config","Never concatenate untrusted variables into install paths","Add a config linter rejecting '..' components","Review shared config changes for path-traversal patterns"],"tags":["config","path","security"],"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"}