jdx/mise · critical
packslip:{project}: this release {}. If the vendor announce
Error message
packslip:{project}: this release {}.
If the vendor announced the change, run `mise packslip forget {project}` and install again; the next release accepted sets the pin. What it means
packslip pins record the signer, attestation source, and provenance of the first accepted release of a project. check_against compares a new release's observed signing metadata against that pin: a different signer or scheme, a repackager attestation where the vendor previously attested, or dropped build provenance all constitute a downgrade and are refused. The error lists all problems and explains how to reset the pin if the vendor legitimately changed its signing setup.
Source
Thrown at src/packslip_pins.rs:153
fn check_against(pin: &Pin, project: &str, observed: Observed<'_>) -> Result<()> {
let signer = signer_of(observed.scheme, observed.key_id);
let mut problems = Vec::new();
if pin.scheme != observed.scheme || pin.signer != signer {
problems.push(format!(
"is signed by {signer} ({}), but {} ({}) signed what mise accepted before",
observed.scheme, pin.signer, pin.scheme
));
}
if pin.attested_by == "vendor" && observed.attested_by == "repackager" {
problems.push(
"is attested by a repackager, but the vendor's own packslip was accepted before".into(),
);
}
if pin.provenance && !observed.provenance {
problems.push("drops the build provenance every artifact linked before".into());
}
if !problems.is_empty() {
bail!(
"packslip:{project}: this release {}.\n\nIf the vendor announced the change, run `mise packslip forget {project}` and install again; the next release accepted sets the pin.",
problems.join(", and ")
);
}
Ok(())
}
/// Set the project's pin from an accepted release, or strengthen it: what
/// got stronger is remembered, what stayed the same is left alone. Checks
/// again under the lock, since the file may have changed since [`check`].
pub(crate) fn record(project: &str, observed: Observed<'_>) -> Result<Pin> {
record_at(&pins_file(), project, observed)
}
pub(crate) fn record_at(path: &Path, project: &str, observed: Observed<'_>) -> Result<Pin> {
let _lock = locked(path)?;
let mut pins = load(path)?;
let signer = signer_of(observed.scheme, observed.key_id);View on GitHub (pinned to afd2eddd3a)
Solutions
- Verify the vendor actually announced a signing/provenance change; check the project's release notes before acting.
- If legitimate, reset the pin: `mise packslip forget <project>`, then install again — the next accepted release sets a fresh pin.
- If not announced, do not reset the pin; treat the release as potentially compromised and verify artifacts out-of-band.
- Compare the reported signer/scheme in the message with the vendor's documented signing identity (e.g. expected workflow OIDC identity).
Example fix
// before: vendor rotated keys, pin refuses the release mise install gh # error: signed by new-workflow, but old-workflow signed before // after confirming the rotation is legitimate mise packslip forget gh && mise install gh # new pin set from accepted release
Defensive patterns
Strategy: validation
Validate before calling
let pinned = mise_packslip_pin(project)?; // signer/scheme/provenance
let observed = observe_release(release)?;
if pinned.signer != signer_of(&observed.scheme, &observed.key_id)
|| (pinned.provenance && !observed.provenance) {
eprintln!("release would downgrade pin for {project}; investigate before forgetting the pin");
} Type guard
fn is_downgrade(pin: &Pin, observed: &Observed) -> bool {
pin.scheme != observed.scheme
|| pin.signer != signer_of(observed.scheme, observed.key_id)
|| (pin.attested_by == "vendor" && observed.attested_by == "repackager")
|| (pin.provenance && !observed.provenance)
} Try / catch
match install(project) {
Err(e) if e.to_string().starts_with("packslip:") => {
// refuse to auto-reset; require explicit human decision
eprintln!("{e}");
Err(e)
}
other => other,
} Prevention
- Treat this error as a potential supply-chain signal; never reflexively run `packslip forget`.
- Confirm any signer/key rotation against the vendor's official announcements first.
- Record expected signing identities per project and audit them when pins are first set.
- Keep mise updated so provenance and attestation checks use current verification logic.
When it happens
Trigger: Installing or verifying a packslip release for a pinned project where the observed Observed{scheme, key_id, attested_by, provenance} mismatches the stored Pin: new signing key/workflow, different signature scheme, repackager instead of vendor attestation, or missing provenance.
Common situations: A vendor rotating signing keys or switching CI workflows (workflow ref changed identity); a release now repackaged by a third party; a release built without provenance attestations; mirror serving substituted artifacts.
Understand the failure class
Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.
Related errors
- packslip:{project} is not on a forge mise knows, so nothing
- the release list expired at {}; the vendor has not published
- packslip release was recorded by the {source} at {time}, aft
- packslip:{project}@{version} was withdrawn by the vendor{}
- the release list of packslip:{project} has sequence {sequenc
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/b8b34e27e2512de7.
Report an issue: GitHub.