{"record":{"id":"ac5ae381cbcfc7a3","repo":"astrid-runtime/astrid","slug":"durable-capsule-id-content-digest-differs-from-a","errorCode":null,"errorMessage":"durable capsule {id} content digest differs from authority receipt","messagePattern":"durable capsule (.+?) content digest differs from authority receipt","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/astrid-capsule-install/src/storage.rs","lineNumber":277,"sourceCode":") -> anyhow::Result<()> {\n    if authority.schema_version != 1 {\n        bail!(\n            \"durable capsule {id} has unsupported authority schema {}\",\n            authority.schema_version\n        );\n    }\n    if authority.capsule_id != id || manifest.package.name != id {\n        bail!(\"durable capsule {id} identity differs across archive and authority\");\n    }\n    if authority.version != manifest.package.version || metadata.version != authority.version {\n        bail!(\"durable capsule {id} version differs across package records\");\n    }\n    let manifest_digest = crate::authority::digest_manifest(manifest_bytes);\n    if authority.manifest_digest != manifest_digest {\n        bail!(\"durable capsule {id} manifest digest differs from authority receipt\");\n    }\n    if authority.content_digest != verification.content_digest() {\n        bail!(\"durable capsule {id} content digest differs from authority receipt\");\n    }\n    let expected_imports = crate::wit::version_map_to_strings(&manifest.imports, |definition| {\n        definition.version.to_string()\n    });\n    if metadata.imports != expected_imports {\n        bail!(\"durable capsule {id} imports differ between metadata and archive\");\n    }\n    let expected_exports = crate::wit::version_map_to_strings(&manifest.exports, |definition| {\n        definition.version.to_string()\n    });\n    if metadata.exports != expected_exports {\n        bail!(\"durable capsule {id} exports differ between metadata and archive\");\n    }\n    if authority.wasm_hash_pinned && metadata.wasm_hash != authority.approved_wasm_hash {\n        bail!(\"durable capsule {id} metadata executable hash differs from authority receipt\");\n    }\n    if let Some(component) = manifest.components.first() {\n        let Some(relative) = component.path.to_str() else {","sourceCodeStart":259,"sourceCodeEnd":295,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-capsule-install/src/storage.rs#L259-L295","documentation":"verify_package_identity throws this when the artifact verification's content digest (digest of the capsule's content/WASM payload) does not match the content_digest pinned in the authority receipt. The receipt records exactly which content the authority approved; any different content on disk is rejected. This prevents loading a swapped or rebuilt binary under an approved capsule identity.","triggerScenarios":"read_verified_durable_package_for_owner verifies the archive's artifact and gets ArtifactVerification::content_digest() != InstalledAuthority.content_digest — e.g. after rebuilding the WASM component, replacing files inside the archive, or associating the capsule with the wrong authority receipt.","commonSituations":"Rebuilding the wasm component with a different toolchain after the authority approved the original build; manually repacking the capsule archive; a corrupted/incomplete download or copy of the archive; two capsules' archives swapped in the install directory.","solutions":["Re-download or restore the original archive whose content matches the approved digest.","Re-submit the new content to the authority for approval and replace the stored receipt with the new content_digest.","Reinstall the capsule from the canonical published artifact rather than a locally rebuilt one.","Verify archive integrity (checksum) after transfer to rule out corruption during copy."],"exampleFix":"// before: rebuilt wasm swapped into approved archive\n// authority.content_digest != blake3(component bytes)\n// after: re-approve the rebuilt content\nlet verification = verify_artifact(&archive)?;\nif authority.content_digest != verification.content_digest() {\n    let receipt = authority.approve_content(&archive)?; // new content_digest\n    store.write_authority(owner, id, &receipt)?;\n}","handlingStrategy":"validation","validationCode":"let verification = verify_artifact(&archive)?;\nif verification.content_digest() != authority.content_digest {\n    // content was replaced/rebuilt; re-approve or restore before loading\n}","typeGuard":"fn content_is_approved(v: &ArtifactVerification, a: &InstalledAuthority) -> bool {\n    v.content_digest() == a.content_digest\n}","tryCatchPattern":"match store.read_verified_durable_package_for_owner(owner, id) {\n    Ok(pkg) => pkg,\n    Err(e) if e.to_string().contains(\"content digest differs from authority receipt\") => {\n        // fetch canonical archive and reinstall\n        let archive = fetch_published(id, &version)?;\n        store.install(owner, &archive)?\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Never swap or rebuild the WASM payload inside an approved capsule; republish instead.","Verify archive checksums after downloads, copies, and restores.","Keep authority receipts and archives versioned together so they cannot be mixed.","Use reproducible builds so a rebuild still matches the approved digest when possible."],"tags":["integrity","capsule","checksum","tampering","rust"],"backgroundTag":"checksum-mismatch","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}