astrid-runtime/astrid · error

capsule content digest does not match its signed provenance

Error message

capsule content digest does not match its signed provenance

What it means

Fired by verify_records when the BLAKE3 content digest recomputed from archive entries differs from the digest covered by the envelope's signature. The capsule's contents were modified after signing (or the signature is invalid/corrupt).

Solutions

  1. Re-download the capsule from the trusted publisher; do not install this copy
  2. Rebuild and re-sign the capsule if you are the author
  3. Check for transmission corruption or tampering
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at crates/astrid-build/src/artifact.rs:372 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/08a7dfa0b1fea1c5. Report an issue: GitHub.

Appendix: source

Thrown at crates/astrid-build/src/artifact.rs:372

fn verify_records(
    records: Vec<ContentRecord>,
    envelope: Option<&[u8]>,
) -> anyhow::Result<ArtifactVerification> {
    let content_digest = digest_records(records)?;
    let Some(bytes) = envelope else {
        return Ok(ArtifactVerification::Unsigned { content_digest });
    };
    let envelope: ProvenanceEnvelope =
        serde_json::from_slice(bytes).context("invalid capsule provenance envelope")?;
    if envelope.schema_version != SCHEMA_VERSION || envelope.algorithm != ALGORITHM {
        bail!(
            "unsupported capsule provenance schema {} / algorithm '{}'",
            envelope.schema_version,
            envelope.algorithm
        );
    }
    if envelope.content_digest != content_digest {
        bail!("capsule content digest does not match its signed provenance");
    }
    envelope
        .signer
        .verify(
            &signature_message(&envelope.content_digest),
            &envelope.signature,
        )
        .context("capsule provenance signature verification failed")?;
    Ok(ArtifactVerification::Signed(VerifiedProvenance {
        content_digest,
        signer: envelope.signer,
        signature: envelope.signature,
    }))
}

fn rewrite_with_provenance(archive_path: &Path, envelope: &[u8]) -> anyhow::Result<()> {
    let parent = archive_path.parent().unwrap_or_else(|| Path::new("."));
    let mut staged = tempfile::NamedTempFile::new_in(parent)

View on GitHub (pinned to affd8760f4)