From 1b2090ed0adc82ba378a94cf086b0924e51a2a4d Mon Sep 17 00:00:00 2001 From: Divy Srivastava Date: Sun, 25 Aug 2024 09:00:34 +0530 Subject: [PATCH 1/5] fix(provenance): ensure slsa object spec compliance --- api/src/provenance.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/api/src/provenance.rs b/api/src/provenance.rs index baf213cc5..5283b4094 100644 --- a/api/src/provenance.rs +++ b/api/src/provenance.rs @@ -104,7 +104,7 @@ pub struct Subject { #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ProvenanceAttestation { - pub subject: Subject, + pub subject: Vec, } pub fn verify( @@ -116,7 +116,9 @@ pub fn verify( let payload = BASE64_STANDARD.decode(&bundle.content.dsse_envelope.payload)?; serde_json::from_slice::(&payload)?.subject - }; + } + .get(0) + .ok_or_else(|| anyhow::anyhow!("Invalid subject"))?; if subject.name != subject_name { bail!("Invalid subject name"); From 034995845739f0a765a5692585a251525d1660a3 Mon Sep 17 00:00:00 2001 From: Divy Srivastava Date: Sun, 25 Aug 2024 09:02:40 +0530 Subject: [PATCH 2/5] Update test --- api/src/api/package.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/api/package.rs b/api/src/api/package.rs index 378780153..11f4ce998 100644 --- a/api/src/api/package.rs +++ b/api/src/api/package.rs @@ -1973,7 +1973,7 @@ mod test { .unwrap(); fn update_bundle_subject(bundle: &mut ProvenanceBundle, subject: Subject) { - let subject = serde_json::json!({ "subject": subject }); + let subject = serde_json::json!({ "subject": [subject] }); bundle.content.dsse_envelope.payload = BASE64_STANDARD .encode(serde_json::to_string(&subject).unwrap().as_bytes()); } From 098130d44c6505a09c356407455836b2f7ae3604 Mon Sep 17 00:00:00 2001 From: Divy Srivastava Date: Sun, 25 Aug 2024 09:08:37 +0530 Subject: [PATCH 3/5] Fix --- api/src/provenance.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/api/src/provenance.rs b/api/src/provenance.rs index 5283b4094..072fd5139 100644 --- a/api/src/provenance.rs +++ b/api/src/provenance.rs @@ -116,9 +116,11 @@ pub fn verify( let payload = BASE64_STANDARD.decode(&bundle.content.dsse_envelope.payload)?; serde_json::from_slice::(&payload)?.subject - } - .get(0) - .ok_or_else(|| anyhow::anyhow!("Invalid subject"))?; + }; + + let subject = subject + .get(0) + .ok_or_else(|| anyhow::anyhow!("Invalid subject"))?; if subject.name != subject_name { bail!("Invalid subject name"); From 7d242991f5c77e96c8e976ee59c5606d61726fe5 Mon Sep 17 00:00:00 2001 From: Divy Srivastava Date: Sun, 25 Aug 2024 09:27:54 +0530 Subject: [PATCH 4/5] Lint --- api/src/provenance.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/provenance.rs b/api/src/provenance.rs index 072fd5139..b1d6377b4 100644 --- a/api/src/provenance.rs +++ b/api/src/provenance.rs @@ -119,7 +119,7 @@ pub fn verify( }; let subject = subject - .get(0) + .first() .ok_or_else(|| anyhow::anyhow!("Invalid subject"))?; if subject.name != subject_name { From e3fed26aae56bc44c7624a290b7ccc1e2d7db738 Mon Sep 17 00:00:00 2001 From: Luca Casonato Date: Mon, 26 Aug 2024 15:14:54 +0200 Subject: [PATCH 5/5] support both single and multiple subjects --- api/src/provenance.rs | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/api/src/provenance.rs b/api/src/provenance.rs index b1d6377b4..0be386993 100644 --- a/api/src/provenance.rs +++ b/api/src/provenance.rs @@ -104,7 +104,17 @@ pub struct Subject { #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ProvenanceAttestation { - pub subject: Vec, + pub subject: ProvenanceAttestationSubject, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(untagged)] +pub enum ProvenanceAttestationSubject { + Subjects(Vec), + // NOTE: this should be removed in the future. It is only here to support + // old Deno CLI versions that sent invalid SLSA attestations where the subject + // was not wrapped in an array. + Subject(Subject), } pub fn verify( @@ -118,9 +128,15 @@ pub fn verify( serde_json::from_slice::(&payload)?.subject }; - let subject = subject - .first() - .ok_or_else(|| anyhow::anyhow!("Invalid subject"))?; + let subject = match subject { + ProvenanceAttestationSubject::Subjects(subjects) => { + if subjects.len() != 1 { + bail!("Invalid subject"); + } + subjects.into_iter().next().unwrap() + } + ProvenanceAttestationSubject::Subject(subject) => subject, + }; if subject.name != subject_name { bail!("Invalid subject name");