{"record":{"id":"d1aeac78945e11e1","repo":"astrid-runtime/astrid","slug":"label-release-metadata-identity-is-invalid","errorCode":null,"errorMessage":"{label} release metadata identity is invalid","messagePattern":"(.+?) release metadata identity is invalid","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/update_channel.rs","lineNumber":656,"sourceCode":"#[allow(clippy::too_many_arguments)]\nfn verify_release_extension(\n    bytes: &[u8],\n    legacy_manifest_bytes: &[u8],\n    pointer: &ChannelPointer,\n    target: &str,\n    expected_kind: &str,\n    expected_targets: &[&str],\n    label: &str,\n) -> anyhow::Result<String> {\n    ensure!(\n        expected_targets.contains(&target),\n        \"{label} release metadata does not support target '{target}'\"\n    );\n    let text = std::str::from_utf8(bytes)\n        .with_context(|| format!(\"{label} release metadata is not UTF-8\"))?;\n    let extension: ReleaseExtension = toml::from_str(text)\n        .with_context(|| format!(\"{label} release metadata is invalid TOML\"))?;\n    ensure!(\n        extension.schema_version == 1\n            && extension.kind == expected_kind\n            && extension.product == PRODUCT\n            && extension.repository == REPOSITORY,\n        \"{label} release metadata identity is invalid\"\n    );\n    canonical_version(&extension.version)?;\n    ensure!(\n        extension.version == pointer.release.version\n            && extension.tag == pointer.release.tag\n            && extension.source_commit == pointer.release.source_commit\n            && extension.release_workflow_identity == pointer.release.release_workflow_identity,\n        \"{label} release metadata does not match the authenticated legacy release\"\n    );\n    ensure!(\n        extension.legacy_release.metadata_asset == pointer.release.metadata_asset\n            && extension.legacy_release.metadata_blake3 == pointer.release.metadata_blake3\n            && blake3::hash(legacy_manifest_bytes).to_hex().as_str()","sourceCodeStart":638,"sourceCodeEnd":674,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/update_channel.rs#L638-L674","documentation":"This error is thrown by verify_release_extension when the parsed release-extension TOML metadata has an identity that does not match what the updater requires: schema_version must be 1, kind must equal the expected extension kind (\"musl\" or \"Windows\"), and product/repository must equal the built-in PRODUCT and REPOSITORY constants. It is a supply-chain integrity check that ensures the downloaded metadata file actually describes this product's release format before any hash or version data from it is trusted.","triggerScenarios":"Calling resolve_target_blake3, verify_musl_extension, or verify_windows_extension with bytes of a metadata file whose TOML parses but has schema_version != 1, a kind field not matching the expected extension kind, or product/repository fields differing from PRODUCT/REPOSITORY (e.g. a metadata file for a different repo or an older schema).","commonSituations":"Pointing the update channel at a third-party fork whose release extensions declare a different repository; serving stale extension metadata generated by an older schema_version; accidentally substituting a musl metadata file where the Windows extension is verified (kind mismatch); hand-edited release metadata.","solutions":["Regenerate the release extension metadata with the current release tooling so schema_version=1 and kind/product/repository match the constants in update_channel.rs","Verify the downloaded metadata asset comes from the authenticated release for PRODUCT/REPOSITORY and was not substituted by a mirror or proxy cache","Check you are passing the right metadata file to the right verifier (musl metadata to verify_musl_extension, Windows metadata to verify_windows_extension)","If you fork the product, update the PRODUCT/REPOSITORY constants or the publishing pipeline to emit matching identity fields"],"exampleFix":"// before: channel config pointing at a fork's extension metadata\nchannel = \"https://mirror.example.com/fork/astrid-release-musl-extension.toml\"\n// after: use the official product's extension metadata\nchannel = \"https://releases.astrid.dev/stable/astrid-release-musl-extension.toml\"","handlingStrategy":"validation","validationCode":"fn metadata_identity_ok(text: &str, product: &str, repository: &str, kind: &str) -> bool {\n    match text.parse::<toml::Table>() {\n        Ok(t) => t.get(\"schema_version\").and_then(|v| v.as_integer()) == Some(1)\n            && t.get(\"kind\").and_then(|v| v.as_str()) == Some(kind)\n            && t.get(\"product\").and_then(|v| v.as_str()) == Some(product)\n            && t.get(\"repository\").and_then(|v| v.as_str()) == Some(repository),\n        Err(_) => false,\n    }\n}","typeGuard":"fn is_valid_extension(e: &ReleaseExtension, expected_kind: &str) -> bool {\n    e.schema_version == 1 && e.kind == expected_kind\n}","tryCatchPattern":"match verify_musl_extension(&bytes, &manifest, &pointer, target) {\n    Ok(blake3) => proceed(blake3),\n    Err(e) if e.to_string().contains(\"identity is invalid\") => {\n        eprintln!(\"metadata does not belong to this product/schema; refusing update\");\n        abort_update();\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Publish release-extension metadata only via the pinned release workflow so schema/kind/product/repository are always correct","Never hand-edit extension metadata TOML files","Pin the channel URL to the official product release origin, not forks or mirrors","Add a CI check that regenerates and verifies metadata identity before publishing a release"],"tags":["security","toml","update-channel","supply-chain"],"backgroundTag":"schema-validation-failed","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"}