{"record":{"id":"d199f57a53421afb","repo":"jdx/mise","slug":"content-level-slsa-verification-rejected-unsafe-ar","errorCode":null,"errorMessage":"content-level SLSA verification rejected unsafe archive path: {}","messagePattern":"content-level SLSA verification rejected unsafe archive path: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src/file.rs","lineNumber":2578,"sourceCode":"            bail!(\n                \"content-level SLSA verification found duplicate installed archive path: {}\",\n                file.name\n            );\n        }\n    }\n    Ok(files)\n}\n\nfn normalize_archive_content_path(path: &Path, strip_components: usize) -> Result<String> {\n    let mut parts = Vec::new();\n    for component in skip_curdir_components(path) {\n        match component {\n            std::path::Component::Normal(part) => parts.push(part.to_string_lossy().to_string()),\n            std::path::Component::CurDir => {}\n            std::path::Component::ParentDir\n            | std::path::Component::RootDir\n            | std::path::Component::Prefix(_) => {\n                bail!(\n                    \"content-level SLSA verification rejected unsafe archive path: {}\",\n                    path.display()\n                )\n            }\n        }\n    }\n    if strip_components > parts.len() {\n        bail!(\n            \"content-level SLSA verification stripped all components from archive path: {}\",\n            path.display()\n        );\n    }\n    let parts = &parts[strip_components..];\n    if parts.is_empty() {\n        bail!(\n            \"content-level SLSA verification stripped all components from archive path: {}\",\n            path.display()\n        );","sourceCodeStart":2560,"sourceCodeEnd":2596,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/file.rs#L2560-L2596","documentation":"During content-level SLSA verification every entry path is normalized, and any component that is '..', a root directory, or a Windows prefix is rejected - the tar/zip traversal guard mirroring sanitize_7z_entry_path. Like the 7z variant, this error indicates a hostile or malformed archive attempting to address paths outside the extraction root, and it should be treated as a security signal.","triggerScenarios":"A tar or zip entry named like ../evil, /etc/passwd, or C:\\x reaches normalize_archive_content_path while archive_content_files enumerates the archive.","commonSituations":"Tampered release asset; malicious archive probing an automated installer; supply-chain incident response.","solutions":["Halt and treat as a security incident: do not extract or install; preserve the artifact for analysis","Inspect the archive non-destructively with tar -tvf or unzip -l to identify the crafted entry","Re-download from the official source and verify checksum and signature before retrying"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// pre-scan entries for traversal patterns before verification/extraction\nfor name in list_archive_entry_names(&archive, format)? {\n    let norm = name.replace('\\\\', \"/\");\n    if norm.split('/').any(|c| c == \"..\") || norm.starts_with('/') {\n        anyhow::bail!(\"unsafe archive path {name:?}; refusing to verify or extract\");\n    }\n}","typeGuard":null,"tryCatchPattern":"match archive_content_files(&archive, format, strip) {\n    Ok(files) => verify_subjects(&files)?,\n    Err(e) if e.to_string().contains(\"rejected unsafe archive path\") => {\n        // fail closed: never downgrade, never extract; treat as supply-chain incident\n        return Err(e.wrap_err(\"path traversal detected in archive; artifact rejected\"));\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Verify provenance/checksums of downloaded archives before any parsing","Treat '..' or absolute-path entries as malicious by default - abort and report, do not sanitize-and-continue","Keep the failure closed: do not fall back to extraction when verification rejects a path"],"tags":["slsa","security","path-traversal","zip-slip","archive","rust","mise"],"backgroundTag":"zip-slip","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}