@@ -195,10 +195,10 @@ def create_security_comment_sarif(diff) -> dict:
195195 scan_failed = False
196196 if len (diff .new_alerts ) == 0 :
197197 for alert in diff .new_alerts :
198- alert : Issue
199198 if alert .error :
200199 scan_failed = True
201200 break
201+
202202 sarif_data = {
203203 "$schema" : "https://json.schemastore.org/sarif-2.1.0.json" ,
204204 "version" : "2.1.0" ,
@@ -225,21 +225,27 @@ def create_security_comment_sarif(diff) -> dict:
225225 rule_id = f"{ pkg_name } =={ pkg_version } "
226226 severity = alert .severity
227227
228- # Generate the correct URL for the alert based on manifest type
229- introduced_list = alert .introduced_by
230- manifest_file = introduced_list [0 ][1 ] if introduced_list and isinstance (introduced_list [0 ], list ) else alert .manifests or "requirements.txt"
231- socket_url = Messages .get_manifest_type_url (manifest_file , pkg_name , pkg_version )
228+ # --- NEW LOGIC: Determine the list of manifest files ---
229+ if alert .introduced_by and isinstance (alert .introduced_by [0 ], list ):
230+ # Extract file names from each introduced_by entry
231+ manifest_files = [entry [1 ] for entry in alert .introduced_by ]
232+ elif alert .manifests :
233+ # Split semicolon-delimited manifest string if necessary
234+ manifest_files = [mf .strip () for mf in alert .manifests .split (";" )]
235+ else :
236+ manifest_files = ["requirements.txt" ]
232237
233- # Prepare descriptions with <br/> replacements
234- short_desc = f"{ alert .props .get ('note' , '' )} <br/><br/>Suggested Action:<br/>{ alert .suggestion } <br/><a href=\" { socket_url } \" >{ socket_url } </a>"
235- full_desc = "{} - {}" .format (alert .title , alert .description .replace ('\r \n ' , '<br/>' ))
238+ # Use the first file for generating the help URL.
239+ socket_url = Messages .get_manifest_type_url (manifest_files [0 ], pkg_name , pkg_version )
236240
237- # Identify the line and snippet in the manifest file
238- line_number , line_content = Messages .find_line_in_file (pkg_name , pkg_version , manifest_file )
239- if line_number < 1 :
240- line_number = 1 # Ensure SARIF compliance
241+ # Prepare the description messages.
242+ short_desc = (
243+ f"{ alert .props .get ('note' , '' )} <br/><br/>Suggested Action:<br/>"
244+ f"{ alert .suggestion } <br/><a href=\" { socket_url } \" >{ socket_url } </a>"
245+ )
246+ full_desc = "{} - {}" .format (alert .title , alert .description .replace ('\r \n ' , '<br/>' ))
241247
242- # Create the rule if not already defined
248+ # Create the rule if not already defined.
243249 if rule_id not in rules_map :
244250 rules_map [rule_id ] = {
245251 "id" : rule_id ,
@@ -252,25 +258,31 @@ def create_security_comment_sarif(diff) -> dict:
252258 },
253259 }
254260
255- # Add the SARIF result
261+ # --- NEW LOGIC: Create separate locations for each manifest file ---
262+ locations = []
263+ for mf in manifest_files :
264+ line_number , line_content = Messages .find_line_in_file (pkg_name , pkg_version , mf )
265+ if line_number < 1 :
266+ line_number = 1 # Ensure SARIF compliance.
267+ locations .append ({
268+ "physicalLocation" : {
269+ "artifactLocation" : {"uri" : mf },
270+ "region" : {
271+ "startLine" : line_number ,
272+ "snippet" : {"text" : line_content },
273+ },
274+ }
275+ })
276+
277+ # Add the SARIF result.
256278 result_obj = {
257279 "ruleId" : rule_id ,
258280 "message" : {"text" : short_desc },
259- "locations" : [
260- {
261- "physicalLocation" : {
262- "artifactLocation" : {"uri" : manifest_file },
263- "region" : {
264- "startLine" : line_number ,
265- "snippet" : {"text" : line_content },
266- },
267- }
268- }
269- ],
281+ "locations" : locations ,
270282 }
271283 results_list .append (result_obj )
272284
273- # Attach rules and results
285+ # Attach rules and results.
274286 sarif_data ["runs" ][0 ]["tool" ]["driver" ]["rules" ] = list (rules_map .values ())
275287 sarif_data ["runs" ][0 ]["results" ] = results_list
276288
0 commit comments