{"record":{"id":"1b0f78f3c3a0994d","repo":"jdx/mise","slug":"brew-cask-cask-metadata-has-no-sha256","errorCode":null,"errorMessage":"brew-cask:{}: cask metadata has no sha256","messagePattern":"brew-cask:(.+?): cask metadata has no sha256","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/cask.rs","lineNumber":1049,"sourceCode":"    let url_hash = &hash::hash_sha256_to_str(&cask.url)[..12];\n    let archive = cache_dir.join(format!(\n        \"{}-{}-{url_hash}-{filename}\",\n        cask.token, cask.version\n    ));\n    if !archive.exists() {\n        HTTP.download_file(&cask.url, &archive, pr).await?;\n        // Strip macOS quarantine so it doesn't propagate into extracted/copied artifacts.\n        let _ = std::process::Command::new(\"xattr\")\n            .args([\"-d\", \"com.apple.quarantine\"])\n            .arg(&archive)\n            .stdout(std::process::Stdio::null())\n            .stderr(std::process::Stdio::null())\n            .status();\n    }\n    match cask.sha256.as_deref() {\n        Some(\"no_check\") => {}\n        Some(sha256) => hash::ensure_checksum(&archive, sha256, pr, \"sha256\")?,\n        None => bail!(\"brew-cask:{}: cask metadata has no sha256\", cask.token),\n    }\n    Ok(archive)\n}\n\nfn extract_archive(cask: &Cask, archive: &Path, pr: Option<&dyn SingleReport>) -> Result<PathBuf> {\n    let extract_dir = crate::dirs::CACHE\n        .join(\"system-brew\")\n        .join(\"cask-extract\")\n        .join(format!(\"{}-{}\", cask.token, cask.version));\n    file::remove_all(&extract_dir)?;\n    file::create_dir_all(&extract_dir)?;\n    let filename = archive\n        .file_name()\n        .and_then(|f| f.to_str())\n        .unwrap_or_default();\n    if is_dmg_archive(archive, filename)? {\n        file::un_dmg(archive, &extract_dir)?;\n    } else {","sourceCodeStart":1031,"sourceCodeEnd":1067,"githubUrl":"https://github.com/jdx/mise/blob/6f52dcdf99e282ef7a7db68c81301fa4618d0f79/src/system/packages/brew/cask.rs#L1031-L1067","documentation":"fetch_archive (src/system/packages/brew/cask.rs:1049) enforces download integrity: after fetching the cask artifact it verifies the sha256 from the cask metadata, honoring the explicit 'no_check' opt-out. If the cask JSON carries no sha256 stanza at all, mise refuses to install an unverified download rather than skip integrity checking by default.","triggerScenarios":"Installing a tapped cask whose api/cask/<token>.json omits the sha256 field. Official homebrew/cask metadata always carries sha256 or 'no_check', so this almost always comes from third-party or internal taps with hand-authored cask JSON.","commonSituations":"Internal taps generated by scripts that drop empty fields; quickly authored casks without checksums; repackaged vendor binaries where the packager skipped the shasum step.","solutions":["If you maintain the tap, add the sha256 stanza to the cask (compute with shasum -a 256 on the artifact), or set it explicitly to no_check if the download genuinely changes per fetch (installer stubs)","Prefer the official homebrew/cask build of the app when one exists","Do not work around by disabling verification — the guard protects against tampered or corrupted downloads"],"exampleFix":"// before (tap's api/cask/myapp.json)\n{ \"token\": \"myapp\", \"version\": \"1.0\", \"url\": \"https://vendor/myapp.dmg\" }\n\n// after\n{ \"token\": \"myapp\", \"version\": \"1.0\", \"url\": \"https://vendor/myapp.dmg\", \"sha256\": \"<64-hex digest>\" }","handlingStrategy":"validation","validationCode":"let cask = fetch_cask_json(token).await?;\nmatch cask.sha256.as_deref() {\n    Some(_) | Some(\"no_check\") => { /* proceed to install */ }\n    None => return Err(anyhow!(\"cask {token} ships no sha256 - refusing to install\")),\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only use taps whose cask JSON carries sha256 (or an explicit no_check for stub installers)","Treat missing checksums in third-party taps as a supply-chain red flag","When authoring internal casks, always compute and embed shasum -a 256 of the artifact"],"tags":["brew-cask","checksum","sha256","integrity","security"],"backgroundTag":"missing-checksum","analyzedSha":"6f52dcdf99e282ef7a7db68c81301fa4618d0f79","analyzedAt":"2026-08-22T10:14:23.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}