{"record":{"id":"38aa0ea05fe049b1","repo":"jdx/mise","slug":"packslip-release-was-recorded-by-the-source-at","errorCode":null,"errorMessage":"packslip release was recorded by the {source} at {time}, after the allowed cutoff {before}; refusing to bypass minimum_release_age","messagePattern":"packslip release was recorded by the (.+?) at (.+?), after the allowed cutoff (.+?); refusing to bypass minimum_release_age","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/backend/packslip.rs","lineNumber":656,"sourceCode":"/// itself resolved — `minimum_release_age` documents both as unfiltered.\nfn selection_already_made(tv: &ToolVersion) -> bool {\n    tv.resolved_from_lockfile() || tv.request_pinned_this_version()\n}\n\nfn check_verified_age(\n    logged_at: Option<&str>,\n    published_at: &str,\n    before: Option<jiff::Timestamp>,\n) -> Result<()> {\n    let Some(before) = before else {\n        return Ok(());\n    };\n    let (time, source) = match logged_at {\n        Some(time) => (time, \"transparency log\"),\n        None => (published_at, \"unlogged manifest\"),\n    };\n    if !verified_age_allowed(logged_at, published_at, Some(before))? {\n        bail!(\n            \"packslip release was recorded by the {source} at {time}, after the allowed cutoff {before}; refusing to bypass minimum_release_age\"\n        );\n    }\n    Ok(())\n}\n\n/// A withdrawal in the vendor's signed list is the end of the matter: no\n/// stamp, mirror, or cached manifest reinstates the version.\nfn refuse_if_withdrawn(project: &str, version: &str, entry: &ReleaseRef) -> Result<()> {\n    if entry.is_yanked() {\n        bail!(\n            \"packslip:{project}@{version} was withdrawn by the vendor{}\",\n            entry\n                .status_reason\n                .as_deref()\n                .map(|r| format!(\": {r}\"))\n                .unwrap_or_default()\n        );","sourceCodeStart":638,"sourceCodeEnd":674,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/backend/packslip.rs#L638-L674","documentation":"mise's minimum_release_age policy delays installing very fresh releases to let supply-chain attacks surface. For a packslip release, the effective timestamp is the transparency-log inclusion time (or the manifest publish time if unlogged). If that timestamp is after the allowed cutoff, mise refuses to install even if every signature verifies.","triggerScenarios":"install_payload or resolve_lock_info calling check_verified_age when verified_age_allowed(logged_at, published_at, before) returns false — i.e. the release was recorded/published more recently than now - minimum_release_age.","commonSituations":"Installing a tool seconds/minutes after the vendor cut a release while minimum_release_age is set (e.g. in an air-gapped or security-hardened org config); CI pinning \"latest\" right after a vendor release.","solutions":["Wait until the release is older than the configured minimum_release_age, then retry.","Pin an older version that predates the cutoff instead of latest.","Lower or unset minimum_release_age (e.g. mise settings or per-tool option) if your risk tolerance allows.","Ensure releases are logged to the transparency log promptly; unlogged manifests fall back to publish time which may be later."],"exampleFix":"// before (mise.toml)\n[settings]\nminimum_release_age = \"7d\"\n\n// after — if the delay is too strict for this tool\n[settings]\nminimum_release_age = \"1d\"","handlingStrategy":"try-catch","validationCode":"// Skip a release younger than the policy cutoff.\nconst cutoff = Date.now() - minReleaseAgeMs;\nif (new Date(release.loggedAt ?? release.publishedAt) > cutoff) {\n  console.warn('release is newer than minimum_release_age; pick an older version');\n}","typeGuard":null,"tryCatchPattern":"try {\n  await miseInstall(tool, { version: 'latest' });\n} catch (e) {\n  if (String(e).includes('minimum_release_age')) {\n    const older = await listVersions(tool); // pick the newest version older than cutoff\n    await miseInstall(tool, { version: older });\n  } else throw e;\n}","preventionTips":["In CI, never resolve `latest` for age-restricted tools immediately after a vendor release.","Pin exact versions in mise.lock so the age check passes deterministically.","Set minimum_release_age deliberately per environment, not org-wide by accident.","Prefer transparency-log-backed vendors so inclusion time (not publish time) drives the check."],"tags":["packslip","supply-chain","release-age","policy"],"backgroundTag":"release-age-policy-violation","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"}