{"record":{"id":"03e800c898c96455","repo":"jdx/mise","slug":"remote-host-bootstrap-command-contains-nul","errorCode":null,"errorMessage":"remote host '{}' bootstrap command contains NUL","messagePattern":"remote host '(.+?)' bootstrap command contains NUL","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/remote.rs","lineNumber":290,"sourceCode":"                \"remote host '{}' must set at most one of mise_bin, remote_mise, or bootstrap_command\",\n                self.name\n            );\n        }\n        for option in &self.ssh_options {\n            validate_value(\"SSH option\", option)?;\n        }\n        for exclude in &self.exclude {\n            validate_value(\"archive exclude\", exclude)?;\n        }\n        if let Some(remote_mise) = &self.remote_mise {\n            validate_remote_executable(remote_mise)?;\n        }\n        if self\n            .bootstrap_command\n            .as_ref()\n            .is_some_and(|command| command.contains('\\0'))\n        {\n            bail!(\"remote host '{}' bootstrap command contains NUL\", self.name);\n        }\n        Ok(())\n    }\n}\n\npub async fn run(\n    host: &RemoteHost,\n    options: &RemoteRunOptions,\n    artifacts: &mut RemoteArtifactResolver,\n) -> Result<()> {\n    let ssh = crate::file::which(\"ssh\").ok_or_else(|| eyre!(\"required command 'ssh' not found\"))?;\n    let tar = crate::file::which(\"tar\").ok_or_else(|| eyre!(\"required command 'tar' not found\"))?;\n    let control_directory = if cfg!(unix) {\n        Some(tempfile::tempdir()?)\n    } else {\n        None\n    };\n    let session = SshSession {","sourceCodeStart":272,"sourceCodeEnd":308,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/system/remote.rs#L272-L308","documentation":"bootstrap_command is executed verbatim on the remote host via sh -lc, and a C string / argv element cannot contain the NUL byte. validate() therefore rejects the host up front when the configured command contains '\\0', instead of letting the SSH exec fail with an opaque error later. In practice the NUL almost always arrives via a TOML \\u0000 escape or programmatic construction of the override.","triggerScenarios":"A mise.toml bootstrap_command string containing an escaped NUL (TOML has no \\0 escape, but \"\\u0000\" is legal and produces the byte), a command generated by tooling that embeds raw NULs, or RemoteOverrides built from code that passes a string with an embedded \\0 to `mise bootstrap remote --bootstrap-command`.","commonSituations":"Copy-pasting a command from a binary-safe source or terminal that introduced a control character; config generated by scripts that concatenate strings without sanitizing; YAML-to-TOML conversion tools emitting \\u0000 placeholders.","solutions":["Retype the bootstrap_command as a plain single-line string with no escape sequences","Grep the config for NUL escapes: search mise.toml for the literal text \\u0000 and remove it","If the command is generated programmatically, strip NUL bytes before writing it into the config or passing the flag"],"exampleFix":"# before (mise.toml)\nbootstrap_command = \"printf 'hi\\u0000' && curl https://mise.run | sh\"\n\n# after\nbootstrap_command = \"curl https://mise.run | sh\"","handlingStrategy":"validation","validationCode":"# reject NUL escapes before running\ngrep -n '\\\\u0000' mise.toml && echo 'bootstrap_command contains a NUL escape — fix it' || echo ok","typeGuard":null,"tryCatchPattern":"if e.to_string().contains(\"bootstrap command contains NUL\") {\n    // sanitize the command string (strip \\0) or retype it in the config\n}","preventionTips":["Write bootstrap_command as plain single-line shell; avoid escape sequences entirely","Sanitize programmatically generated commands: command.replace('\\0', \"\")","TOML has no \\0 escape; treat any \\u0000 in a command string as a bug in the generator"],"tags":["mise","config","validation","bootstrap","remote","sanitization"],"backgroundTag":"nul-byte-in-argument","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}