{"record":{"id":"cad763feb231cc63","repo":"jdx/mise","slug":"the-packslip-at-is-not-the-one-the-signed-relea","errorCode":null,"errorMessage":"the packslip at {} is not the one the signed release list points at (sha256 {actual}, list says {expected})","messagePattern":"the packslip at (.+?) is not the one the signed release list points at \\(sha256 (.+?), list says (.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/backend/packslip.rs","lineNumber":1119,"sourceCode":"            // digest is already the one checked below.\n            None => (self.locate_bundle(&project, &tv, &pin, &opts).await?, None),\n        };\n        let bundle_path = tv.download_path().join(bundle_name(&project));\n        file::create_dir_all(tv.download_path())?;\n        ctx.pr.set_message(\"download packslip\".into());\n        HTTP.download_file_with_headers(\n            &located.url,\n            &bundle_path,\n            &located.headers,\n            Some(ctx.pr.as_ref()),\n        )\n        .await?;\n        let pinned: Vec<&String> = located.digest.iter().chain(vendor_digest.iter()).collect();\n        if !pinned.is_empty() {\n            let (actual, _) = packslip::digest_file(&bundle_path)?;\n            for expected in pinned {\n                if &actual != expected {\n                    bail!(\n                        \"the packslip at {} is not the one the signed release list points at (sha256 {actual}, list says {expected})\",\n                        located.url\n                    );\n                }\n            }\n        }\n        let bundle = file::read_to_string(&bundle_path)?;\n        ctx.pr.set_message(\"verify packslip\".into());\n        let verified = verify_bundle(&bundle, &pin, require_log, &[])\n            .wrap_err_with(|| format!(\"verifying the packslip of {}\", tv.style()))?;\n        let payload = packslip::sigstore::peek_statement(&bundle).map_err(|e| eyre!(\"{e}\"))?;\n        let statement: Statement = serde_json::from_slice(&payload)?;\n        if verified.project != project {\n            bail!(\"the packslip is for {}, not {project}\", verified.project);\n        }\n        if verified.version != tv.version {\n            bail!(\n                \"the packslip says version {}, not {}; the release's tag and its manifest disagree\",","sourceCodeStart":1101,"sourceCodeEnd":1137,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/backend/packslip.rs#L1101-L1137","documentation":"Before verification, mise hashes the downloaded packslip bundle file and compares it against the digests pinned in the release list (and any stamp). If the file at the located URL does not hash to the listed digest, the bundle served is not the one the signed release list points at. This catches substituted or tampered bundles before signature verification is even attempted.","triggerScenarios":"install_payload (via install/install_version_) when packslip::digest_file of the downloaded bundle yields a sha256 that differs from any entry in located.digest or vendor_digest — CDN/proxy substitution, cache poisoning, or the vendor replaced the artifact without updating the list.","commonSituations":"Corporate proxy rewrites or caches artifacts; a mirror serves stale bundles; the vendor force-pushed a re-uploaded release asset; transient network corruption on download.","solutions":["Delete the cached bundle and re-download (`mise cache clean` or remove the install dir), then `mise install` again","Bypass the mirror/proxy (set MISE_* network settings to fetch directly) and retry","Check the vendor's release page: if the artifact was genuinely replaced, refresh the signed release list entry in mise.lock"],"exampleFix":"# before: install fails with digest mismatch\nmise cache clean\n# after: fresh download, digest matches again\nmise install","handlingStrategy":"validation","validationCode":"use sha2::{Digest, Sha256};\nfn bundle_matches_release_list(bundle_bytes: &[u8], expected: &[String]) -> bool {\n    let actual = hex::encode(Sha256::digest(bundle_bytes));\n    expected.iter().any(|e| e.eq_ignore_ascii_case(&actual))\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Clear caches after suspected proxy/CDN substitution incidents","Avoid untrusted mirrors for release artifacts","Re-download and re-hash whenever an install reports a digest mismatch"],"tags":["packslip","sha256","integrity","download"],"backgroundTag":"checksum-mismatch","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}