From 8e4075632853d644f172ef704206ab3173ba45ae Mon Sep 17 00:00:00 2001 From: Nando Vieira Date: Fri, 16 Jan 2026 17:00:39 -0300 Subject: [PATCH 1/2] Handle contract build info when multiple attestations are available. --- .../src/commands/contract/info/build.rs | 32 +++++++++++++------ 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/cmd/soroban-cli/src/commands/contract/info/build.rs b/cmd/soroban-cli/src/commands/contract/info/build.rs index fe7ad43dc..98886fa2c 100644 --- a/cmd/soroban-cli/src/commands/contract/info/build.rs +++ b/cmd/soroban-cli/src/commands/contract/info/build.rs @@ -84,16 +84,28 @@ impl Cmd { print.infoln(format!("Collecting GitHub attestation from {url}")); let resp = http::client().get(url).send().await?; let resp: gh_attest_resp::Root = resp.json().await?; - let Some(attestation) = resp.attestations.first() else { - return Err(Error::AttestationNotFound); - }; - let Ok(payload) = base64::engine::general_purpose::STANDARD - .decode(&attestation.bundle.dsse_envelope.payload) - else { - return Err(Error::AttestationInvalid); - }; - let payload: gh_payload::Root = serde_json::from_slice(&payload)?; + + // Find the SLSA provenance attestation (not the Release attestation) + // GitHub may attach multiple attestations, and we need the one with predicate_type + // matching "https://slsa.dev/provenance/v1" + let payload = resp + .attestations + .iter() + .find_map(|attestation| { + let payload = base64::engine::general_purpose::STANDARD + .decode(&attestation.bundle.dsse_envelope.payload) + .ok()?; + let payload: gh_payload::Root = serde_json::from_slice(&payload).ok()?; + if payload.predicate_type == "https://slsa.dev/provenance/v1" { + Some(payload) + } else { + None + } + }) + .ok_or(Error::AttestationNotFound)?; + print.checkln("Attestation found linked to GitHub Actions Workflow Run:"); + let workflow_repo = payload .predicate .build_definition @@ -117,7 +129,7 @@ impl Cmd { .build_definition .resolved_dependencies .first() - .unwrap() + .ok_or(Error::AttestationInvalid)? .digest .git_commit; let runner_environment = payload From f8ac6f0dfe8e3e21dc401fc8e3e6bf86268bf0b9 Mon Sep 17 00:00:00 2001 From: Nando Vieira Date: Fri, 16 Jan 2026 17:08:31 -0300 Subject: [PATCH 2/2] Be more consise with then_some. --- cmd/soroban-cli/src/commands/contract/info/build.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/cmd/soroban-cli/src/commands/contract/info/build.rs b/cmd/soroban-cli/src/commands/contract/info/build.rs index 98886fa2c..08a16a890 100644 --- a/cmd/soroban-cli/src/commands/contract/info/build.rs +++ b/cmd/soroban-cli/src/commands/contract/info/build.rs @@ -96,11 +96,8 @@ impl Cmd { .decode(&attestation.bundle.dsse_envelope.payload) .ok()?; let payload: gh_payload::Root = serde_json::from_slice(&payload).ok()?; - if payload.predicate_type == "https://slsa.dev/provenance/v1" { - Some(payload) - } else { - None - } + + (payload.predicate_type == "https://slsa.dev/provenance/v1").then_some(payload) }) .ok_or(Error::AttestationNotFound)?;