{"record":{"id":"e93b4f0ffd5316e4","repo":"jdx/mise","slug":"unsafe-elf-interpreter-path-interpreter","errorCode":null,"errorMessage":"unsafe ELF interpreter path: {interpreter:?}","messagePattern":"unsafe ELF interpreter path: (.+?)","errorType":"exception","errorClass":"eyre::Report","httpStatus":null,"severity":"error","filePath":"src/system/remote.rs","lineNumber":1421,"sourceCode":"        let size = usize::try_from(read_elf_int(\n            bytes,\n            start + size_field,\n            if class == 1 { 4 } else { 8 },\n            little_endian,\n        )?)?;\n        let value = bytes\n            .get(\n                offset\n                    ..offset\n                        .checked_add(size)\n                        .ok_or_else(|| eyre!(\"invalid ELF interpreter\"))?,\n            )\n            .ok_or_else(|| eyre!(\"truncated ELF interpreter\"))?;\n        let value = value.strip_suffix(&[0]).unwrap_or(value);\n        let interpreter = String::from_utf8(value.to_vec())?;\n        if !interpreter.starts_with('/') || interpreter.contains('\\0') || interpreter.contains('\\n')\n        {\n            bail!(\"unsafe ELF interpreter path: {interpreter:?}\");\n        }\n        return Ok(Some(interpreter));\n    }\n    Ok(None)\n}\n\nfn read_elf_int(bytes: &[u8], offset: usize, size: usize, little_endian: bool) -> Result<u64> {\n    let value = bytes\n        .get(\n            offset\n                ..offset\n                    .checked_add(size)\n                    .ok_or_else(|| eyre!(\"invalid ELF field\"))?,\n        )\n        .ok_or_else(|| eyre!(\"truncated ELF field\"))?;\n    let mut padded = [0_u8; 8];\n    if little_endian {\n        padded[..size].copy_from_slice(value);","sourceCodeStart":1403,"sourceCodeEnd":1439,"githubUrl":"https://github.com/jdx/mise/blob/6f52dcdf99e282ef7a7db68c81301fa4618d0f79/src/system/remote.rs#L1403-L1439","documentation":"Thrown by elf_interpreter when the PT_INTERP string is present but fails the safety check: it must be an absolute path (start with '/') and contain no embedded NUL or newline. This guard exists because the interpreter path is later shell-quoted into a remote 'sh -c' command (validate_default_binary_compatibility), so a malformed value could inject shell syntax. Real loaders like /lib64/ld-linux-x86-64.so.1 always pass; failure indicates corruption or a crafted binary.","triggerScenarios":"A mise_bin whose PT_INTERP segment was corrupted so the path is relative or contains control characters; a maliciously crafted binary attempting to smuggle characters into the remote shell command.","commonSituations":"Supply-chain caution: binaries from untrusted sources; damaged files where the interpreter string runs into adjacent data; packers that rewrite PT_INTERP incorrectly.","solutions":["Discard the binary and obtain it from a trusted source (official release or your own build)","Inspect the interpreter: readelf -l mise | grep 'Requesting program interpreter' must show an absolute path","Treat repeated occurrences as a security signal: verify checksums/signatures before retrying"],"exampleFix":"# before: untrusted binary with malformed interpreter\nreadelf -l ./downloaded/mise | grep interpreter\n# [Requesting program interpreter: lib/ld-linux.so.2\\n...]  -> relative/newline -> rejected\n\n# after: use the signed official artifact\ncurl -fsSL https://mise.run | sh\nreadelf -l ~/.local/bin/mise | grep interpreter\n# [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]","handlingStrategy":"validation","validationCode":"# Confirm the interpreter is an absolute, sane path before upload\nreadelf -l ./mise | grep 'Requesting program interpreter'\n# expect: [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]\n# anything relative/newline-separated is corrupt or hostile: discard the binary","typeGuard":"fn interpreter_path_safe(interp: &str) -> bool {\n    interp.starts_with('/') && !interp.contains('\\0') && !interp.contains('\\n')\n}","tryCatchPattern":"match elf_interpreter(&bytes) {\n    Err(e) if e.to_string().contains(\"unsafe ELF interpreter path\") => {\n        // treat as untrusted input: never shell-quote this into a remote command\n        eyre::bail!(\"binary rejected: unsafe PT_INTERP; verify provenance before retrying\");\n    }\n    other => other?,\n}","preventionTips":["Only use binaries from signed releases or your own builds; verify checksums first","If this fires repeatedly, investigate as a potential supply-chain/incident signal","Never bypass the check by hand-crafting the remote loader command"],"tags":["mise","elf","security","path-validation","shell-injection","remote-bootstrap"],"backgroundTag":"invalid-executable-format","analyzedSha":"6f52dcdf99e282ef7a7db68c81301fa4618d0f79","analyzedAt":"2026-08-22T10:14:23.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}