{"record":{"id":"5d80184cebcff283","repo":"jdx/mise","slug":"lockfile-generation-would-downgrade-additional-artifact","errorCode":null,"errorMessage":"lockfile generation would downgrade additional artifact provenance; previous files were preserved","messagePattern":"lockfile generation would downgrade additional artifact provenance; previous files were preserved","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/lockfile/generate.rs","lineNumber":812,"sourceCode":"    // Preserve identities across reordering, then pair replaced URLs in their\n    // configured order so version upgrades retain the previous trust baseline.\n    let mut replacements = new.additional_artifacts.iter().filter(|artifact| {\n        !old.additional_artifacts\n            .iter()\n            .any(|old| old.url == artifact.url)\n    });\n    for artifact in &old.additional_artifacts {\n        let replacement = new\n            .additional_artifacts\n            .iter()\n            .find(|new| new.url == artifact.url)\n            .or_else(|| replacements.next());\n        if provenance_is_downgrade(\n            artifact.provenance.as_ref(),\n            replacement.and_then(|a| a.provenance.as_ref()),\n            packslip_signer_replaces_provenance,\n        ) {\n            bail!(\n                \"lockfile generation would downgrade additional artifact provenance; previous files were preserved\"\n            );\n        }\n    }\n    Ok(())\n}\n\nfn provenance_is_downgrade(\n    old: Option<&ProvenanceType>,\n    new: Option<&ProvenanceType>,\n    packslip_signer_replaces_provenance: bool,\n) -> bool {\n    if packslip_signer_replaces_provenance\n        && old.is_some_and(ProvenanceType::is_github_attestations)\n    {\n        return false;\n    }\n    new < old","sourceCodeStart":794,"sourceCodeEnd":830,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/lockfile/generate.rs#L794-L830","documentation":"Beyond the primary artifact, lockfiles record provenance for additional artifacts. During generation, each old additional artifact is paired with its replacement (in configured order, handling reordering); if the replacement's provenance is a downgrade relative to what was recorded, `ensure_no_downgrade` aborts and preserves the previous files.","triggerScenarios":"Regenerating a lockfile where an additional artifact (extra platform/binary artifact) previously had provenance but the newly resolved replacement artifact lacks it or has weaker provenance, with `packslip_signer_replaces_provenance` in effect for packslip backends.","commonSituations":"Upstream stopped attesting some per-platform artifacts but not others; switching backends for extra artifacts; partial attestation coverage in a new release; mirrors lacking provenance for secondary artifacts.","solutions":["Check the specific artifact's attestation availability upstream for the target version","Keep using the backend (e.g. packslip:) that provides provenance for all artifacts","Re-enable attestation-related settings if they were turned off","If the weaker provenance is accepted knowingly, clear the recorded provenance for that entry first (manual lockfile review)"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"for artifact in new_entry.additional_artifacts {\n    if artifact.provenance.is_none() {\n        // a replacement artifact lacks provenance — generation would downgrade\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Verify attestation coverage for all per-platform artifacts of a release, not just the primary one","Keep packslip backends for tools that publish signed manifests","Regenerate lockfiles on a platform matrix so all additional artifacts are checked","Don't mix backends for primary vs additional artifacts of the same tool"],"tags":["lockfile","provenance","artifacts","security"],"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"}