@@ -82,7 +82,7 @@ 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- best_line = - 1
85+ best_line = 1
8686 snippet = None
8787
8888 for i , line in enumerate (lines , start = 1 ):
@@ -97,10 +97,10 @@ def find_line_in_file(packagename: str, packageversion: str, manifest_file: str)
9797 else :
9898 return 1 , f'"{ found_key } ": { found_info } '
9999 else :
100- return - 1 , f"{ packagename } { packageversion } (not found in { manifest_file } )"
100+ return 1 , f"{ packagename } { packageversion } (not found in { manifest_file } )"
101101
102102 except (FileNotFoundError , json .JSONDecodeError ):
103- return - 1 , f"Error reading { manifest_file } "
103+ return 1 , f"Error reading { manifest_file } "
104104
105105 # ----------------------------------------------------
106106 # 2) Text-based / line-based manifests
@@ -148,28 +148,49 @@ def find_line_in_file(packagename: str, packageversion: str, manifest_file: str)
148148 return line_number , line_content .strip ()
149149
150150 except FileNotFoundError :
151- return - 1 , f"{ manifest_file } not found"
151+ return 1 , f"{ manifest_file } not found"
152152 except Exception as e :
153- return - 1 , f"Error reading { manifest_file } : { e } "
153+ return 1 , f"Error reading { manifest_file } : { e } "
154154
155- return - 1 , f"{ packagename } { packageversion } (not found)"
155+ return 1 , f"{ packagename } { packageversion } (not found)"
156156
157157 @staticmethod
158- def create_security_comment_sarif ( diff : Diff ) -> dict :
158+ def get_manifest_type_url ( manifest_file : str , pkg_name : str , pkg_version : str ) -> str :
159159 """
160- Create SARIF-compliant output from the diff report, including line references
161- and a link to the Socket docs in the fullDescription. Also converts any \r \n
162- into <br/> so they render properly in GitHub's SARIF display.
160+ Determine the correct URL path based on the manifest file type.
163161 """
164- # Check if there's a blocking error in new alerts
165- scan_failed = False
166- if len (diff .new_alerts ) == 0 :
167- for alert in diff .new_alerts :
168- if alert .error :
169- scan_failed = True
170- break
162+ manifest_to_url_prefix = {
163+ "package.json" : "npm" ,
164+ "package-lock.json" : "npm" ,
165+ "yarn.lock" : "npm" ,
166+ "pnpm-lock.yaml" : "npm" ,
167+ "requirements.txt" : "pypi" ,
168+ "pyproject.toml" : "pypi" ,
169+ "Pipfile" : "pypi" ,
170+ "go.mod" : "go" ,
171+ "go.sum" : "go" ,
172+ "pom.xml" : "maven" ,
173+ "build.gradle" : "maven" ,
174+ ".csproj" : "nuget" ,
175+ ".fsproj" : "nuget" ,
176+ "paket.dependencies" : "nuget" ,
177+ "Cargo.toml" : "cargo" ,
178+ "Gemfile" : "rubygems" ,
179+ "Gemfile.lock" : "rubygems" ,
180+ "composer.json" : "composer" ,
181+ "vcpkg.json" : "vcpkg" ,
182+ }
183+ 184+ file_type = Path (manifest_file ).name
185+ url_prefix = manifest_to_url_prefix .get (file_type , "unknown" )
186+ return f"https://socket.dev/{ url_prefix } /package/{ pkg_name } /alerts/{ pkg_version } "
171187
172- # Basic SARIF skeleton
188+ @staticmethod
189+ def create_security_comment_sarif (diff ) -> dict :
190+ """
191+ Create SARIF-compliant output from the diff report, including dynamic URL generation
192+ based on manifest type and improved <br/> formatting for GitHub SARIF display.
193+ """
173194 sarif_data = {
174195 "$schema" : "https://json.schemastore.org/sarif-2.1.0.json" ,
175196 "version" : "2.1.0" ,
@@ -196,40 +217,34 @@ def create_security_comment_sarif(diff: Diff) -> dict:
196217 rule_id = f"{ pkg_name } =={ pkg_version } "
197218 severity = alert .severity
198219
199- # Convert any \r\n in short desc to <br/> so they display properly
200- short_desc_raw = f"{ alert .props .get ('note' , '' )} \r \n \r \n Suggested Action:\r \n { alert .suggestion } "
201- short_desc = short_desc_raw .replace ("\r \n " , "<br/>" )
202- 203- # Build link to Socket docs, e.g. "https://socket.dev/npm/package/foo/alerts/1.2.3"
204- socket_url = f"https://socket.dev/npm/package/{ pkg_name } /alerts/{ pkg_version } "
205- 206- # Also convert \r\n in the main description to <br/>, then append the Socket docs link
207- base_desc = alert .description .replace ("\r \n " , "<br/>" )
208- full_desc_raw = f"{ alert .title } - { base_desc } <br/>{ socket_url } "
209- 210- # Identify the manifest file and line
220+ # Generate the correct URL for the alert based on manifest type
211221 introduced_list = alert .introduced_by
212- if introduced_list and isinstance (introduced_list [0 ], list ) and len (introduced_list [0 ]) > 1 :
213- manifest_file = introduced_list [0 ][1 ]
214- else :
215- manifest_file = alert .manifests or "requirements.txt"
222+ manifest_file = introduced_list [0 ][1 ] if introduced_list and isinstance (introduced_list [0 ], list ) else alert .manifests or "requirements.txt"
223+ socket_url = Messages .get_manifest_type_url (manifest_file , pkg_name , pkg_version )
224+ 225+ # Prepare descriptions with <br/> replacements
226+ short_desc = f"{ alert .props .get ('note' , '' )} <br/><br/>Suggested Action:<br/>{ alert .suggestion } <br/><a href=\" { socket_url } \" >{ socket_url } </a>"
227+ full_desc = f"{ alert .title } - { alert .description .replace ('\r \n ' , '<br/>' )} "
216228
229+ # Identify the line and snippet in the manifest file
217230 line_number , line_content = Messages .find_line_in_file (pkg_name , pkg_version , manifest_file )
231+ if line_number < 1 :
232+ line_number = 1 # Ensure SARIF compliance
218233
219- # If not already defined, create a rule for this package
234+ # Create the rule if not already defined
220235 if rule_id not in rules_map :
221236 rules_map [rule_id ] = {
222237 "id" : rule_id ,
223238 "name" : f"{ pkg_name } =={ pkg_version } " ,
224239 "shortDescription" : {"text" : f"Alert generated for { rule_id } by Socket Security" },
225- "fullDescription" : {"text" : full_desc_raw },
226- "helpUri" : alert . url ,
240+ "fullDescription" : {"text" : full_desc },
241+ "helpUri" : socket_url ,
227242 "defaultConfiguration" : {
228243 "level" : Messages .map_severity_to_sarif (severity )
229244 },
230245 }
231246
232- # Create a SARIF " result" referencing the line where we found the match
247+ # Add the SARIF result
233248 result_obj = {
234249 "ruleId" : rule_id ,
235250 "message" : {"text" : short_desc },
@@ -247,7 +262,7 @@ def create_security_comment_sarif(diff: Diff) -> dict:
247262 }
248263 results_list .append (result_obj )
249264
250- # Attach our rules and results to the SARIF data
265+ # Attach rules and results
251266 sarif_data ["runs" ][0 ]["tool" ]["driver" ]["rules" ] = list (rules_map .values ())
252267 sarif_data ["runs" ][0 ]["results" ] = results_list
253268
0 commit comments