@@ -82,7 +82,11 @@ def find_line_in_file(packagename: str, packageversion: str, manifest_file: str)
8282 needle_key = f'"{ found_key } ":' # e.g. "node_modules/axios":
8383 needle_version = f'"version": "{ packageversion } "'
8484 lines = raw_text .splitlines ()
85+ < << << << HEAD
8586 best_line = 1
87+ == == == =
88+ best_line = - 1
89+ > >> >> >> 7 ddb4537518fa762da7ebebff2044ce71e720f3c
8690 snippet = None
8791
8892 for i , line in enumerate (lines , start = 1 ):
@@ -97,10 +101,17 @@ def find_line_in_file(packagename: str, packageversion: str, manifest_file: str)
97101 else :
98102 return 1 , f'"{ found_key } ": { found_info } '
99103 else :
104+ << << << < HEAD
100105 return 1 , f"{ packagename } { packageversion } (not found in { manifest_file } )"
101106
102107 except (FileNotFoundError , json .JSONDecodeError ):
103108 return 1 , f"Error reading { manifest_file } "
109+ == == == =
110+ return - 1 , f"{ packagename } { packageversion } (not found in { manifest_file } )"
111+
112+ except (FileNotFoundError , json .JSONDecodeError ):
113+ return - 1 , f"Error reading { manifest_file } "
114+ >> >> >> > 7 ddb4537518fa762da7ebebff2044ce71e720f3c
104115
105116 # ----------------------------------------------------
106117 # 2) Text-based / line-based manifests
@@ -142,6 +153,7 @@ def find_line_in_file(packagename: str, packageversion: str, manifest_file: str)
142153 for line_number , line_content in enumerate (lines , start = 1 ):
143154 # For Python conditional dependencies, ignore everything after first ';'
144155 line_main = line_content .split (";" , 1 )[0 ].strip ()
156+ << << << < HEAD
145157
146158 # Use a case-insensitive regex search
147159 if re .search (searchstring , line_main , re .IGNORECASE ):
@@ -191,6 +203,36 @@ def create_security_comment_sarif(diff) -> dict:
191203 Create SARIF-compliant output from the diff report, including dynamic URL generation
192204 based on manifest type and improved <br/> formatting for GitHub SARIF display.
193205 """
206+ == == == =
207+
208+ # Use a case-insensitive regex search
209+ if re .search (searchstring , line_main , re .IGNORECASE ):
210+ return line_number , line_content .strip ()
211+
212+ except FileNotFoundError :
213+ return - 1 , f"{ manifest_file } not found"
214+ except Exception as e :
215+ return - 1 , f"Error reading { manifest_file } : { e } "
216+
217+ return - 1 , f"{ packagename } { packageversion } (not found)"
218+
219+ @staticmethod
220+ def create_security_comment_sarif (diff : Diff ) -> dict :
221+ """
222+ Create SARIF-compliant output from the diff report, including line references
223+ and a link to the Socket docs in the fullDescription. Also converts any \r \n
224+ into <br/> so they render properly in GitHub's SARIF display.
225+ """
226+ # Check if there's a blocking error in new alerts
227+ scan_failed = False
228+ if len (diff .new_alerts ) == 0 :
229+ for alert in diff .new_alerts :
230+ if alert .error :
231+ scan_failed = True
232+ break
233+
234+ # Basic SARIF skeleton
235+ > >> >> >> 7 ddb4537518fa762da7ebebff2044ce71e720f3c
194236 sarif_data = {
195237 "$schema" : "https://json.schemastore.org/sarif-2.1.0.json" ,
196238 "version" : "2.1.0" ,
@@ -217,11 +259,27 @@ def create_security_comment_sarif(diff) -> dict:
217259 rule_id = f"{ pkg_name } =={ pkg_version } "
218260 severity = alert .severity
219261
262+ < << << << HEAD
220263 # Generate the correct URL for the alert based on manifest type
264+ == == == =
265+ # Convert any \r\n in short desc to <br/> so they display properly
266+ short_desc_raw = f"{ alert .props .get ('note' , '' )} \r \n \r \n Suggested Action:\r \n { alert .suggestion } "
267+ short_desc = short_desc_raw .replace ("\r \n " , "<br/>" )
268+
269+ # Build link to Socket docs, e.g. "https://socket.dev/npm/package/foo/alerts/1.2.3"
270+ socket_url = f"https://socket.dev/npm/package/{ pkg_name } /alerts/{ pkg_version } "
271+
272+ # Also convert \r\n in the main description to <br/>, then append the Socket docs link
273+ base_desc = alert .description .replace ("\r \n " , "<br/>" )
274+ full_desc_raw = f"{ alert .title } - { base_desc } <br/>{ socket_url } "
275+
276+ # Identify the manifest file and line
277+ >> >> >> > 7 ddb4537518fa762da7ebebff2044ce71e720f3c
221278 introduced_list = alert .introduced_by
222279 manifest_file = introduced_list [0 ][1 ] if introduced_list and isinstance (introduced_list [0 ], list ) else alert .manifests or "requirements.txt"
223280 socket_url = Messages .get_manifest_type_url (manifest_file , pkg_name , pkg_version )
224281
282+ < << << << HEAD
225283 # Prepare descriptions with <br/> replacements
226284 short_desc = f"{ alert .props .get ('note' , '' )} <br/><br/>Suggested Action:<br/>{ alert .suggestion } "
227285 full_desc = f"{ alert .title } - { alert .description .replace ('\r \n ' , '<br/>' )} \r \n <a href=\" { socket_url } \" >{ socket_url } </a>"
@@ -232,19 +290,33 @@ def create_security_comment_sarif(diff) -> dict:
232290 line_number = 1 # Ensure SARIF compliance
233291
234292 # Create the rule if not already defined
293+ == == == =
294+ line_number , line_content = Messages .find_line_in_file (pkg_name , pkg_version , manifest_file )
295+
296+ # If not already defined, create a rule for this package
297+ > >> >> >> 7 ddb4537518fa762da7ebebff2044ce71e720f3c
235298 if rule_id not in rules_map :
236299 rules_map [rule_id ] = {
237300 "id" : rule_id ,
238301 "name" : f"{ pkg_name } =={ pkg_version } " ,
239302 "shortDescription" : {"text" : f"Alert generated for { rule_id } by Socket Security" },
303+ << << << < HEAD
240304 "fullDescription" : {"text" : full_desc },
241305 "helpUri" : socket_url ,
306+ == == == =
307+ "fullDescription" : {"text" : full_desc_raw },
308+ "helpUri" : alert .url ,
309+ > >> >> >> 7 ddb4537518fa762da7ebebff2044ce71e720f3c
242310 "defaultConfiguration" : {
243311 "level" : Messages .map_severity_to_sarif (severity )
244312 },
245313 }
246314
315+ << << << < HEAD
247316 # Add the SARIF result
317+ == == == =
318+ # Create a SARIF "result" referencing the line where we found the match
319+ >> >> >> > 7 ddb4537518fa762da7ebebff2044ce71e720f3c
248320 result_obj = {
249321 "ruleId" : rule_id ,
250322 "message" : {"text" : short_desc },
@@ -262,7 +334,11 @@ def create_security_comment_sarif(diff) -> dict:
262334 }
263335 results_list .append (result_obj )
264336
337+ < << << << HEAD
265338 # Attach rules and results
339+ == == == =
340+ # Attach our rules and results to the SARIF data
341+ >> >> >> > 7 ddb4537518fa762da7ebebff2044ce71e720f3c
266342 sarif_data ["runs" ][0 ]["tool" ]["driver" ]["rules" ] = list (rules_map .values ())
267343 sarif_data ["runs" ][0 ]["results" ] = results_list
268344
0 commit comments