@@ -67,7 +67,13 @@ def __init__(self, ecosystem=ECOSYSTEM.PYPI) -> None:
6767 ".semgrep_logs" ,
6868 ]
6969
70- def analyze (self , path , info = None , rules = None , name : Optional [str ] = None , version : Optional [str ] = None ) -> dict :
70+ def analyze (
71+ self ,
72+ path ,
73+ info = None ,
74+ rules = None ,
75+ name : Optional [str ] = None ,
76+ version : Optional [str ] = None ) -> dict :
7177 """
7278 Analyzes a package in the given path
7379
@@ -87,23 +93,33 @@ def analyze(self, path, info=None, rules=None, name: Optional[str] = None, versi
8793 sourcecode_results = None
8894
8995 # populate results, errors, and number of issues
90- metadata_results = self .analyze_metadata (path , info , rules , name , version )
96+ metadata_results = self .analyze_metadata (
97+ path , info , rules , name , version )
9198 sourcecode_results = self .analyze_sourcecode (path , rules )
9299
93100 # Concatenate dictionaries together
94101 issues = metadata_results ["issues" ] + sourcecode_results ["issues" ]
95102 results = metadata_results ["results" ] | sourcecode_results ["results" ]
96103 errors = metadata_results ["errors" ] | sourcecode_results ["errors" ]
97104
98- output = {"issues" : issues , "errors" : errors , "results" : results , "path" : path }
105+ output = {
106+ "issues" : issues ,
107+ "errors" : errors ,
108+ "results" : results ,
109+ "path" : path }
99110 # Including extension info - pending discussion
100111 # if info is not None:
101112 # output["package_info"] = info
102113
103114 return output
104115
105- def analyze_metadata (self , path : str , info , rules = None , name : Optional [str ] = None ,
106- version : Optional [str ] = None ) -> dict :
116+ def analyze_metadata (
117+ self ,
118+ path : str ,
119+ info ,
120+ rules = None ,
121+ name : Optional [str ] = None ,
122+ version : Optional [str ] = None ) -> dict :
107123 """
108124 Analyzes the metadata of a given package
109125
@@ -132,7 +148,8 @@ def analyze_metadata(self, path: str, info, rules=None, name: Optional[str] = No
132148 for rule in all_rules :
133149 try :
134150 log .debug (f"Running rule { rule } against package '{ name } '" )
135- rule_matches , message = self .metadata_detectors [rule ].detect (info , path , name , version )
151+ rule_matches , message = self .metadata_detectors [rule ].detect (
152+ info , path , name , version )
136153 results [rule ] = None
137154 if rule_matches :
138155 issues += 1
@@ -162,7 +179,11 @@ def analyze_sourcecode(self, path, rules=None) -> dict:
162179 results = semgrepscan_results ["results" ] | yarascan_results ["results" ]
163180 errors = semgrepscan_results ["errors" ] | yarascan_results ["errors" ]
164181
165- return {"issues" : issues , "errors" : errors , "results" : results , "path" : path }
182+ return {
183+ "issues" : issues ,
184+ "errors" : errors ,
185+ "results" : results ,
186+ "path" : path }
166187
167188 def analyze_yara (self , path : str , rules : Optional [set ] = None ) -> dict :
168189 """
@@ -212,30 +233,32 @@ def analyze_yara(self, path: str, rules: Optional[set] = None) -> dict:
212233 continue
213234
214235 scan_file_target_abspath = os .path .join (root , f )
215- scan_file_target_relpath = os .path .relpath (scan_file_target_abspath , path )
236+ scan_file_target_relpath = os .path .relpath (
237+ scan_file_target_abspath , path )
216238
217239 matches = scan_rules .match (scan_file_target_abspath )
218240 for m in matches :
219241 rule_name = m .rule
220-
221242 if rule_name in verbose_rules :
222243 # For verbose rules, we only show that the rule was triggered in the matching file
223- # We're logging appearances once instead of issue-counting
244+ # We're logging appearances once instead of
245+ # issue-counting
224246 file_already_reported = any (
225247 finding ["location" ].startswith (scan_file_target_relpath + ":" )
226248 for finding in rule_results [rule_name ]
227249 )
228-
229250 if not file_already_reported :
230251 finding = {
231252 "location" : f"{ scan_file_target_relpath } :1" ,
232- "code" : f"Rule triggered in file (matches hidden for brevity)" ,
233- 'message' : m .meta .get ("description" , f"{ rule_name } rule matched" )
234- }
253+ "code" : f'{ "Rule triggered in file (matches hidden for brevity)" } ' ,
254+ 'message' : m .meta .get (
255+ "description" ,
256+ f"{ rule_name } rule matched" )}
235257 issues += 1
236258 rule_results [rule_name ].append (finding )
237259 else :
238- # For non-verbose rules, show detailed matches as before
260+ # For non-verbose rules, show detailed matches as
261+ # before
239262 for s in m .strings :
240263 for i in s .instances :
241264 finding = {
@@ -259,7 +282,10 @@ def analyze_yara(self, path: str, rules: Optional[set] = None) -> dict:
259282 except Exception as e :
260283 errors ["rules-all" ] = f"failed to run rule: { str (e )} "
261284
262- return {"results" : results | rule_results , "errors" : errors , "issues" : issues }
285+ return {
286+ "results" : results | rule_results ,
287+ "errors" : errors ,
288+ "issues" : issues }
263289
264290 def analyze_semgrep (self , path , rules = None ) -> dict :
265291 """
@@ -284,10 +310,8 @@ def analyze_semgrep(self, path, rules=None) -> dict:
284310 errors = {}
285311 issues = 0
286312
287- rules_path = list (map (
288- lambda rule_name : os .path .join (SOURCECODE_RULES_PATH , f"{ rule_name } .yml" ),
289- all_rules
290- ))
313+ rules_path = list (map (lambda rule_name : os .path .join (
314+ SOURCECODE_RULES_PATH , f"{ rule_name } .yml" ), all_rules ))
291315
292316 if len (rules_path ) == 0 :
293317 log .debug ("No semgrep code rules to run" )
@@ -296,7 +320,8 @@ def analyze_semgrep(self, path, rules=None) -> dict:
296320 try :
297321 log .debug (f"Running semgrep code rules against { path } " )
298322 response = self ._invoke_semgrep (target = path , rules = rules_path )
299- rule_results = self ._format_semgrep_response (response , targetpath = targetpath )
323+ rule_results = self ._format_semgrep_response (
324+ response , targetpath = targetpath )
300325 issues += sum (len (res ) for res in rule_results .values ())
301326
302327 results = results | rule_results
@@ -308,7 +333,9 @@ def analyze_semgrep(self, path, rules=None) -> dict:
308333 def _invoke_semgrep (self , target : str , rules : Iterable [str ]):
309334 try :
310335 SEMGREP_MAX_TARGET_BYTES = int (
311- os .getenv ("GUARDDOG_SEMGREP_MAX_TARGET_BYTES" , MAX_BYTES_DEFAULT ))
336+ os .getenv (
337+ "GUARDDOG_SEMGREP_MAX_TARGET_BYTES" ,
338+ MAX_BYTES_DEFAULT ))
312339 SEMGREP_TIMEOUT = int (
313340 os .getenv ("GUARDDOG_SEMGREP_TIMEOUT" , SEMGREP_TIMEOUT_DEFAULT ))
314341 cmd = ["semgrep" ]
@@ -325,7 +352,11 @@ def _invoke_semgrep(self, target: str, rules: Iterable[str]):
325352 cmd .append (f"--max-target-bytes={ SEMGREP_MAX_TARGET_BYTES } " )
326353 cmd .append (target )
327354 log .debug (f"Invoking semgrep with command line: { ' ' .join (cmd )} " )
328- result = subprocess .run (cmd , capture_output = True , check = True , encoding = "utf-8" )
355+ result = subprocess .run (
356+ cmd ,
357+ capture_output = True ,
358+ check = True ,
359+ encoding = "utf-8" )
329360 return json .loads (str (result .stdout ))
330361 except FileNotFoundError :
331362 raise Exception ("unable to find semgrep binary" )
@@ -379,9 +410,9 @@ def _format_semgrep_response(self, response, rule=None, targetpath=None):
379410 file_path = os .path .abspath (result ["path" ])
380411 code = self .trim_code_snippet (
381412 self .get_snippet (
382- file_path = file_path , start_line = start_line , end_line = end_line
383- )
384- )
413+ file_path = file_path ,
414+ start_line = start_line ,
415+ end_line = end_line ) )
385416 if targetpath :
386417 file_path = os .path .relpath (file_path , targetpath )
387418
@@ -400,7 +431,11 @@ def _format_semgrep_response(self, response, rule=None, targetpath=None):
400431
401432 return results
402433
403- def get_snippet (self , file_path : str , start_line : int , end_line : int ) -> str :
434+ def get_snippet (
435+ self ,
436+ file_path : str ,
437+ start_line : int ,
438+ end_line : int ) -> str :
404439 """
405440 Returns the code snippet between start_line and stop_line in a file
406441
0 commit comments