{"record":{"id":"c04701c9f7c3c1b2","repo":"jdx/mise","slug":"remote-mktemp-returned-an-unsafe-staging-path-pa","errorCode":null,"errorMessage":"remote mktemp returned an unsafe staging path: {path:?}","messagePattern":"remote mktemp returned an unsafe staging path: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/remote.rs","lineNumber":2189,"sourceCode":"    if value.starts_with('-') || value.chars().any(char::is_whitespace) {\n        bail!(\"invalid remote {kind}: {value}\");\n    }\n    Ok(())\n}\n\nfn validate_value(kind: &str, value: &str) -> Result<()> {\n    if value.is_empty() || value.contains('\\0') {\n        bail!(\"remote {kind} cannot be empty or contain NUL\");\n    }\n    Ok(())\n}\n\nfn validate_staging_path(path: &str) -> Result<()> {\n    if !path.starts_with(\"/tmp/mise-bootstrap.\")\n        || path[\"/tmp/mise-bootstrap.\".len()..].is_empty()\n        || path.chars().any(char::is_whitespace)\n    {\n        bail!(\"remote mktemp returned an unsafe staging path: {path:?}\");\n    }\n    Ok(())\n}\n\nfn validated_remote_command(command: &str) -> Result<String> {\n    if !command.starts_with('/') || command.contains(['\\0', '\\n', '\\r']) {\n        bail!(\"bootstrap_command returned an unsafe mise path: {command:?}\");\n    }\n    Ok(command.to_string())\n}\n\nfn validated_remote_command_output(output: &str) -> Result<String> {\n    validated_remote_command(output.strip_suffix('\\n').unwrap_or(output))\n}\n\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']) {","sourceCodeStart":2171,"sourceCodeEnd":2207,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/remote.rs#L2171-L2207","documentation":"`validate_staging_path` checks the path returned by the remote `mktemp -d` call: it must start with `/tmp/mise-bootstrap.`, have a non-empty suffix, and contain no whitespace. If the remote mktemp produced anything else, mise refuses to use it, since the staging path is later embedded in remote commands and an unexpected path could break quoting or be a hostile/pre-mounted location.","triggerScenarios":"Remote `mktemp -d` template yields a path outside the expected `/tmp/mise-bootstrap.*` prefix (custom TMPDIR, restricted tmp layout), an empty suffix, or a path containing spaces.","commonSituations":"Remote host with TMPDIR set to a non-/tmp location; hardened/immutable /tmp with unusual mktemp wrappers; site-specific mktemp templates producing paths with spaces.","solutions":["Ensure the remote environment uses the default mktemp behavior — unset/normalize TMPDIR for the SSH session (e.g. `ssh host 'unset TMPDIR; ...'` or in the remote shell profile)","Inspect what `ssh host mktemp -d /tmp/mise-bootstrap.XXXXXX` actually returns and align it with the expected prefix","If the host cannot provide /tmp paths, run the bootstrap without the remote transport or pre-provision a compliant staging directory"],"exampleFix":"// before\n# remote profile sets TMPDIR=/var/user tmp\n$ ssh host mktemp -d /tmp/mise-bootstrap.XXXXXX\n/var/tmp/mise-bootstrap.abc   # unexpected prefix\n// after\n# normalize remote env\n$ ssh host 'TMPDIR=/tmp mktemp -d /tmp/mise-bootstrap.XXXXXX'\n/tmp/mise-bootstrap.x9K2q","handlingStrategy":"validation","validationCode":"# verify the remote mktemp path shape before running the flow\np=$(ssh \"$host\" 'mktemp -d /tmp/mise-bootstrap.XXXXXX') \\\\\\n  || exit 1\ncase \"$p\" in\n  /tmp/mise-bootstrap.?*) ;;\n  *) echo \"unexpected staging path: $p\"; exit 1;;\nesac","typeGuard":"fn is_safe_staging_path(p: &str) -> bool {\n    p.starts_with(\"/tmp/mise-bootstrap.\")\n        && p.len() > \"/tmp/mise-bootstrap.\".len()\n        && !p.chars().any(char::is_whitespace)\n}","tryCatchPattern":"let path = remote_mktemp().await?;\nif !is_safe_staging_path(&path) {\n    // normalize TMPDIR on the host and retry once\n    retry_with_default_tmpdir().await?;\n}","preventionTips":["Keep TMPDIR unset/default in remote shell profiles used by bootstrap","Verify remote mktemp output shape when hardening hosts","Avoid custom mktemp wrappers or templates on build hosts"],"tags":["remote","ssh","validation","staging-path"],"backgroundTag":"unexpected-response-shape","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"}