2020from codesectools .sasts import SASTS_ALL
2121from codesectools .sasts .all .graphics import ProjectGraphics
2222from codesectools .sasts .all .sast import AllSAST
23- from codesectools .sasts .core .sast import PrebuiltSAST
23+ from codesectools .sasts .core .sast import PrebuiltBuildlessSAST , PrebuiltSAST
24+ from codesectools .utils import group_successive
2425
2526
2627def build_cli () -> typer .Typer :
@@ -72,11 +73,11 @@ def analyze(
7273 ),
7374 ],
7475 # Additional options
75- artifact_dir : Annotated [
76+ artifacts : Annotated [
7677 Path | None ,
7778 typer .Option (
7879 help = "Pre-built artifacts directory (for PrebuiltSAST only)" ,
79- metavar = "ARTIFACT_DIR " ,
80+ metavar = "ARTIFACTS " ,
8081 ),
8182 ] = None ,
8283 # Common NOT REQUIRED option
@@ -90,27 +91,28 @@ def analyze(
9091 ) -> None :
9192 """Run analysis on the current project with all available SAST tools."""
9293 for sast in all_sast .sasts_by_lang .get (lang , []):
93- if isinstance (sast , PrebuiltSAST ) and artifact_dir is None :
94- print (f"{ sast .name } required pre-built artifacts for analysis" )
94+ if isinstance (sast , PrebuiltBuildlessSAST ) and artifacts is None :
9595 print (
96- "Please provide the directory with artifacts (with --artifact-dir) to include this tool "
96+ f"[i] { sast . name } can use pre-built artifacts ({ sast . artefact_name } { sast . artefact_type } ) for more accurate analysis "
9797 )
98+ print ("[i]Use the flag --artifacts to provide the artifacts" )
99+ elif isinstance (sast , PrebuiltSAST ) and artifacts is None :
100+ print (
101+ f"[b]Skipping { sast .name } because it requires pre-built artifacts ({ sast .artefact_name } { sast .artefact_type } )"
102+ )
103+ print ("[b]Use the flag --artifacts to provide the artifacts" )
98104 continue
99105
100106 output_dir = sast .output_dir / Path .cwd ().name
101107 if output_dir .is_dir ():
102108 if overwrite :
103109 shutil .rmtree (output_dir )
104- sast .run_analysis (
105- lang , Path .cwd (), output_dir , artifact_dir = artifact_dir
106- )
110+ sast .run_analysis (lang , Path .cwd (), output_dir , artifacts = artifacts )
107111 else :
108112 print (f"Found existing analysis result at { output_dir } " )
109113 print ("Use --overwrite to overwrite it" )
110114 else :
111- sast .run_analysis (
112- lang , Path .cwd (), output_dir , artifact_dir = artifact_dir
113- )
115+ sast .run_analysis (lang , Path .cwd (), output_dir , artifacts = artifacts )
114116
115117 @cli .command (help = "Benchmark a dataset using all SAST tools." )
116118 def benchmark (
@@ -323,20 +325,43 @@ def report(
323325 defect_table .add_column ("SAST" , justify = "center" )
324326 defect_table .add_column ("CWE" , justify = "center" )
325327 defect_table .add_column ("Message" )
326- for defect in sorted (set (defect_data ["raw" ]), key = lambda d : d .location [0 ]):
327- if location := defect .location :
328- start , end = location
329- shortcut = Text (f"{ start } " , style = Style (link = f"#L{ start } " ))
328+ rows = []
329+ for defect in defect_data ["raw" ]:
330+ groups = group_successive (defect .lines )
331+ if groups :
332+ for group in groups :
333+ start , end = group [0 ], group [- 1 ]
334+ shortcut = Text (f"{ start } " , style = Style (link = f"#L{ start } " ))
335+ cwe_link = (
336+ Text (
337+ f"CWE-{ defect .cwe .id } " ,
338+ style = Style (
339+ link = f"https://cwe.mitre.org/data/definitions/{ defect .cwe .id } .html"
340+ ),
341+ )
342+ if defect .cwe .id != - 1
343+ else "None"
344+ )
345+ rows .append (
346+ (start , shortcut , defect .sast , cwe_link , defect .message )
347+ )
330348 else :
331- shortcut = "None"
332- cwe_link = Text (
333- f"CWE-{ defect .cwe .id } " ,
334- style = Style (
335- link = f"https://cwe.mitre.org/data/definitions/{ defect .cwe .id } .html"
336- ),
337- )
338- defect_table .add_row (shortcut , defect .sast , cwe_link , defect .message )
349+ cwe_link = (
350+ Text (
351+ f"CWE-{ defect .cwe .id } " ,
352+ style = Style (
353+ link = f"https://cwe.mitre.org/data/definitions/{ defect .cwe .id } .html"
354+ ),
355+ )
356+ if defect .cwe .id != - 1
357+ else "None"
358+ )
359+ rows .append (
360+ (float ("inf" ), "None" , defect .sast , cwe_link , defect .message )
361+ )
339362
363+ for row in sorted (rows , key = lambda r : r [0 ]):
364+ defect_table .add_row (* row [1 :])
340365 defect_page .print (defect_table )
341366
342367 # Syntax
@@ -352,7 +377,11 @@ def report(
352377 for location in defect_data ["locations" ]:
353378 sast , cwe , message , (start , end ) = location
354379 for i in range (start , end + 1 ):
355- text = f"<b>{ sast } </b>: <i>{ message } (CWE-{ cwe .id } )</i>"
380+ text = (
381+ f"<b>{ sast } </b>: <i>{ message } (CWE-{ cwe .id } )</i>"
382+ if cwe .id != - 1
383+ else f"<b>{ sast } </b>: <i>{ message } </i>"
384+ )
356385 if highlights .get (i ):
357386 highlights [i ].add (text )
358387 else :
0 commit comments