{"record":{"id":"3fb9e5cd9daf62a6","repo":"jdx/mise","slug":"content-level-slsa-verification-found-duplicate-in","errorCode":null,"errorMessage":"content-level SLSA verification found duplicate installed archive path: {}","messagePattern":"content-level SLSA verification found duplicate installed archive path: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/file.rs","lineNumber":2751,"sourceCode":"    let mut buf = [0; 8192];\n    loop {\n        let n = reader.read(&mut buf)?;\n        if n == 0 {\n            break;\n        }\n        hasher.update(&buf[..n]);\n    }\n    Ok(hex::encode(hasher.finalize()))\n}\n\nfn validate_archive_content_files(files: Vec<ArchiveContent>) -> Result<Vec<ArchiveContent>> {\n    if files.is_empty() {\n        bail!(\"content-level SLSA verification found no regular files in archive\");\n    }\n    let mut names = std::collections::HashSet::new();\n    for file in &files {\n        if !names.insert(file.name.clone()) {\n            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!(","sourceCodeStart":2733,"sourceCodeEnd":2769,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/file.rs#L2733-L2769","documentation":"Content-level SLSA verification hashes every regular file at its installed path. If two files in the archive map to the same installed path after strip-component normalization, the digest set is ambiguous, so mise rejects the archive instead of producing a non-reproducible verification.","triggerScenarios":"`mise install` with content-level SLSA verification where two archive entries (often differing only by case, a `./` prefix, or a duplicate entry appended to the tarball) normalize to the same installed path.","commonSituations":"Hand-built or duplicated-entry tarballs; archives mixing `./dir/file` and `dir/file` entries; case-insensitive filesystem collisions between two archive paths that differ only in case.","solutions":["Inspect the archive with `tar tf <file> | sort | uniq -d` (after applying strip_components) to find duplicate entries","Rebuild or re-download the archive from upstream; a clean official release usually has no duplicate entries","Adjust strip_components in the recipe if a single normalization step is collapsing distinct paths","Pin to an earlier upstream version whose release archives were not affected"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"tar -tf tool.tar.gz | sed 's|^\\./||' | sort | uniq -d","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check for duplicate archive entries with sort/uniq before publishing or pinning artifacts","Prefer official release archives over hand-rebuilt tarballs","Watch for case-collisions when installing to case-insensitive filesystems"],"tags":["slsa","archive","verification","duplicate-paths"],"backgroundTag":"checksum-mismatch","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"}