@@ -164,7 +164,12 @@ def self.check_attestation(bottle, signing_repo, signing_workflow = nil, subject
164164
165165 # `gh attestation verify` returns a JSON array of one or more results,
166166 # for all attestations that match the input's digest. We want to additionally
167- # filter these down to just the attestation whose subject matches the bottle's name.
167+ # filter these down to just the attestation whose subject(s) contain the bottle's name.
168+ # As of 2024-12-04 GitHub's Artifact Attestation feature can put multiple subjects
169+ # in a single attestation, so we check every subject in each attestation
170+ # and select the first attestation with a matching subject.
171+ # In particular, this happens with v2.0.0 and later of the
172+ # `actions/attest-build-provenance` action.
168173 subject = bottle . filename . to_s if subject . blank?
169174
170175 attestation = if bottle . tag . to_sym == :all
@@ -175,12 +180,15 @@ def self.check_attestation(bottle, signing_repo, signing_workflow = nil, subject
175180 # This is sound insofar as the signature has already been verified. However,
176181 # longer term, we should also directly attest to `:all`-tagged bottles.
177182 attestations . find do |a |
178- actual_subject = a . dig ( "verificationResult" , "statement" , "subject" , 0 , "name" )
179- actual_subject . start_with? "#{ bottle . filename . name } --#{ bottle . filename . version } "
183+ candidate_subjects = a . dig ( "verificationResult" , "statement" , "subject" )
184+ candidate_subjects . any? do |candidate |
185+ candidate [ "name" ] . start_with? "#{ bottle . filename . name } --#{ bottle . filename . version } "
186+ end
180187 end
181188 else
182189 attestations . find do |a |
183- a . dig ( "verificationResult" , "statement" , "subject" , 0 , "name" ) == subject
190+ candidate_subjects = a . dig ( "verificationResult" , "statement" , "subject" )
191+ candidate_subjects . any? { |candidate | candidate [ "name" ] == subject }
184192 end
185193 end
186194
0 commit comments