11use std:: collections:: HashSet ;
2- use serde_json:: Value ;
32use std:: io:: { self , Read } ;
43use crate :: Config ;
54use uuid:: Uuid ;
@@ -8,6 +7,8 @@ use std::process::Command;
87use crate :: cicd:: { * } ;
98use crate :: log:: debug;
109use reqwest:: header;
10+ use crate :: scanners:: parsers:: ScanParserFactory ;
11+ use serde_json:: Value ;
1112
1213pub fn run_command ( base_cmd : & String , mut command : Command ) -> String {
1314 match which:: which ( base_cmd) {
@@ -91,123 +92,27 @@ pub fn read_file_report(config: &Config, file_path: &str) {
9192}
9293
9394pub fn parse_scan ( config : & Config , input : String , save_to_file : bool ) {
94- debug ( "Parsing the scan report json" ) ;
95-
96- let mut paths: Vec < String > = Vec :: new ( ) ;
97- let mut scanner = String :: new ( ) ;
98- let data: std:: result:: Result < Value , _ > = serde_json:: from_str ( & input) ;
99-
100- match data {
101- Ok ( data) => {
102- let schema = data. get ( "$schema" ) . and_then ( |v| v. as_str ( ) ) . unwrap_or ( "unknown" ) ;
103-
104- if input. contains ( "semgrep.dev" ) {
105- debug ( "Detected semgrep schema" ) ;
106- scanner = "semgrep" . to_string ( ) ;
107- if let Some ( results) = data. get ( "results" ) . and_then ( |v| v. as_array ( ) ) {
108- for result in results {
109- if let Some ( path) = result. get ( "path" ) . and_then ( |v| v. as_str ( ) ) {
110- paths. push ( path. to_string ( ) ) ;
111- }
112- }
113- }
114- } else if schema. contains ( "sarif" ) {
115- debug ( "Detected sarif schema" ) ;
116- let run = data. get ( "runs" ) . and_then ( |v| v. as_array ( ) ) . and_then ( |v| v. get ( 0 ) ) ;
117- let driver = run. and_then ( |v| v. get ( "tool" ) ) . and_then ( |v| v. get ( "driver" ) ) . and_then ( |v| v. get ( "name" ) ) ;
118- let tool = driver. and_then ( |v| v. as_str ( ) ) . unwrap_or ( "unknown" ) ;
119-
120- if tool == "SnykCode" {
121- debug ( "Detected snyk version of sarif schema" ) ;
122- scanner = "snyk" . to_string ( ) ;
123- } else if tool == "CodeQL" {
124- debug ( "Detected codeql version of sarif schema" ) ;
125- scanner = "codeql" . to_string ( ) ;
126- } else {
127- eprintln ! ( "{} is not supported as this time." , tool) ;
128- std:: process:: exit ( 1 ) ;
129- }
130-
131- if let Some ( runs) = data. get ( "runs" ) . and_then ( |v| v. as_array ( ) ) {
132- for run in runs {
133- if let Some ( results) = run. get ( "results" ) . and_then ( |v| v. as_array ( ) ) {
134- for result in results {
135- if let Some ( locations) = result. get ( "locations" ) . and_then ( |v| v. as_array ( ) ) {
136- for location in locations {
137- if let Some ( uri) = location. get ( "physicalLocation" ) . and_then ( |v| v. get ( "artifactLocation" ) ) . and_then ( |v| v. get ( "uri" ) ) . and_then ( |v| v. as_str ( ) ) {
138- paths. push ( uri. to_string ( ) ) ;
139- }
140- }
141- }
142- }
143- }
144- }
145- }
146- // checkmarx report generated by CLI
147- } else if data. get ( "totalCount" ) . is_some ( ) && data. get ( "results" ) . is_some ( ) && data. get ( "scanID" ) . is_some ( ) {
148- debug ( "Detected checkmarx cli schema" ) ;
149- scanner = "checkmarx" . to_string ( ) ;
150- if let Some ( results) = data. get ( "results" ) . and_then ( |v| v. as_array ( ) ) {
151- for result in results {
152- if let Some ( data) = result. get ( "data" ) {
153- if let Some ( nodes) = data. get ( "nodes" ) . and_then ( |v| v. as_array ( ) ) {
154- for node in nodes {
155- if let Some ( path) = node. get ( "fileName" ) {
156- if let Some ( truncated_path) = path. as_str ( ) {
157- paths. push ( truncated_path. get ( 1 ..) . unwrap_or ( "" ) . to_string ( ) ) ;
158- }
159- }
160- }
161- }
162- }
163- }
164- }
165- // for checkmarx report generated by web
166- } else if data. get ( "scanResults" ) . is_some ( ) && data. get ( "reportId" ) . is_some ( ) {
167- debug ( "Detected checkmarx web schema" ) ;
168- scanner = "checkmarx" . to_string ( ) ;
169- if let Some ( scan_results) = data. get ( "scanResults" ) {
170- if let Some ( sast) = scan_results. get ( "sast" ) {
171- if let Some ( languges) = sast. get ( "languages" ) . and_then ( |v| v. as_array ( ) ) {
172- for language in languges {
173- if let Some ( queries) = language. get ( "queries" ) . and_then ( |v| v. as_array ( ) ) {
174- for query in queries {
175- if let Some ( vulns) = query. get ( "vulnerabilities" ) . and_then ( |v| v. as_array ( ) ) {
176- for vuln in vulns {
177- if let Some ( nodes) = vuln. get ( "nodes" ) . and_then ( |v| v. as_array ( ) ) {
178- for node in nodes {
179- if let Some ( path) = node. get ( "fileName" ) {
180- if let Some ( truncated_path) = path. as_str ( ) {
181- paths. push ( truncated_path. get ( 1 ..) . unwrap_or ( "" ) . to_string ( ) ) ;
182- }
183- }
184- }
185- }
186- }
187- }
188- }
189- }
190- }
191- }
192- }
193- }
194- } else {
195- debug ( "Couldn't detect what kind of report this is." )
95+ debug ( "Parsing the scan report" ) ;
96+
97+ // Remove BOM (Byte Order Mark) if present
98+ let cleaned_input = input. trim_start_matches ( '\u{feff}' ) . trim ( ) ;
99+
100+ let parser_factory = ScanParserFactory :: new ( ) ;
101+
102+ match parser_factory. parse_scan_data ( cleaned_input) {
103+ Ok ( parse_result) => {
104+ if parse_result. paths . is_empty ( ) {
105+ eprintln ! ( "No issues found in scan report, exiting." ) ;
106+ std:: process:: exit ( 0 ) ;
196107 }
108+
109+ upload_scan ( config, parse_result. paths , parse_result. scanner , cleaned_input. to_string ( ) , save_to_file) ;
197110 }
198- Err ( e) => {
199- eprintln ! ( "Failed to parse JSON report: {}" , e) ;
200- eprintln ! ( "Only reports in JSON format are supported." ) ;
111+ Err ( error_message) => {
112+ eprintln ! ( "{}" , error_message) ;
201113 std:: process:: exit ( 1 ) ;
202114 }
203115 }
204-
205- if paths. len ( ) == 0 {
206- eprintln ! ( "No issues found in scan report, exiting." ) ;
207- std:: process:: exit ( 0 ) ;
208- }
209-
210- upload_scan ( config, paths, scanner, input, save_to_file) ;
211116}
212117
213118pub fn upload_scan ( config : & Config , paths : Vec < String > , scanner : String , input : String , save_to_file : bool ) {
0 commit comments