@@ -84,7 +84,7 @@ func createGitHubSecretAlertsAPIPath(scope string, target string) (apiURL string
8484 replacer := strings .NewReplacer ("{owner}" , owner , "{repo}" , repo )
8585 apiURL = replacer .Replace (repositoryAlertsURL )
8686 default :
87- err = fmt .Errorf ("Invalid API target. " )
87+ err = fmt .Errorf ("invalid API target" )
8888 }
8989 return apiURL , err
9090}
@@ -159,13 +159,11 @@ func callGitHubAPI(client *api.RESTClient, requestPath string, parseType interfa
159159 nextPage := response .Header .Get ("Link" )
160160 responseBody , err := io .ReadAll (response .Body )
161161 if err != nil {
162- fmt .Println ("ERROR: Unable to read next page link" )
163162 return response .StatusCode , nextPage , err
164163 }
165164
166165 err = decodeJSONResponse (responseBody , & parseType )
167166 if err != nil {
168- fmt .Println ("ERROR: Unable to decode JSON response" )
169167 return response .StatusCode , nextPage , err
170168 }
171169
@@ -176,7 +174,6 @@ func decodeJSONResponse(body []byte, parseType interface{}) error {
176174 decoder := json .NewDecoder (bytes .NewReader (body ))
177175 err := decoder .Decode (& parseType )
178176 if err != nil {
179- fmt .Println ("ERROR: Unable to decode JSON response" )
180177 return err
181178 }
182179
@@ -200,11 +197,11 @@ func validateProvider(provider string) (err error) {
200197 providerList = append (providerList , key )
201198 }
202199 for _ , item := range providerList {
203- if strings .ToLower (item ) == strings . ToLower ( provider ) {
200+ if strings .EqualFold (item , provider ) {
204201 return nil
205202 }
206203 }
207- err = fmt .Errorf (Red ( "Invalid provider: " + provider + "\n Valid providers are: " + strings .Join (providerList , ", " ) ))
204+ err = fmt .Errorf ("Invalid provider: " + provider + "\n Valid providers are: " + strings .Join (providerList , ", " ))
208205 return err
209206}
210207
@@ -250,6 +247,20 @@ func getScopeAndTarget() (scope string, target string, err error) {
250247 target = organization
251248 } else if repository != "" {
252249 scope = "repository"
250+ repoPattern := regexp .MustCompile (`^[^/]+/[^/]+$` )
251+ if ! repoPattern .MatchString (repository ) {
252+ err = errors .New ("repository must follow the format 'owner/repository'" )
253+ return "" , "" , err
254+ }
255+ // check if secret scanning is enabled for the repository:
256+ secretScanningEnabled , err := checkSecretScanningSetting (repository )
257+ if err != nil {
258+ return "" , "" , err
259+ }
260+ if ! secretScanningEnabled {
261+ err = errors .New ("Secret scanning is not enabled for the repository: " + repository )
262+ return "" , "" , err
263+ }
253264 target = repository
254265 }
255266 return scope , target , err
@@ -341,11 +352,10 @@ func generateCSVReport(alerts []Alert, scope string, validity_check bool) (err e
341352 now := time .Now ()
342353 // Format the time as YYYYMMDD-HHMMSS
343354 timestamp := now .Format ("20060102-150405" )
344- filename := "secretscanningreport -" + scope + "-" + timestamp + ".csv"
355+ filename := "SecretScanningReport -" + scope + "-" + timestamp + ".csv"
345356 // Create a CSV file
346357 file , err := os .Create (filename )
347358 if err != nil {
348- fmt .Println ("ERROR: Error creating CSV file." )
349359 return err
350360 }
351361 defer file .Close ()
@@ -381,7 +391,6 @@ func generateCSVReport(alerts []Alert, scope string, validity_check bool) (err e
381391 counter ++
382392 }
383393 if err := writer .Error (); err != nil {
384- fmt .Println ("ERROR: Error writing to CSV file." )
385394 return err
386395 }
387396 fmt .Println (Blue ("CSV report generated: " + filename ))
@@ -420,19 +429,17 @@ func verifyAlerts(alerts []Alert) (alertsOutput []Alert, err error) {
420429 }
421430 client , err := api .NewHTTPClient (opts )
422431 if err != nil {
423- fmt .Println ("ERROR: Unable to create HTTP client." )
424432 return alerts , err
425433 }
426434 // send a request to the validation endpoint:
427435 var response * http.Response
428436 if secret_validation_method == "POST" {
429437 var body io.Reader
430- req , err := http .NewRequest ("POST" , alert .Validity_endpoint , body )
438+ req , _ := http .NewRequest ("POST" , alert .Validity_endpoint , body )
431439 req .Header .Set ("Authorization" , "Bearer " + alert .Secret )
432440 req .Header .Set ("Content-Type" , secret_validation_content_type )
433441 req .Header .Set ("User-Agent" , "gh-secret-scanning" )
434442 response , err = client .Do (req )
435- // response, err = client.Post(alert.Validity_endpoint, secret_validation_content_type, body)
436443 if err != nil {
437444 fmt .Println ("WARNING: Unable to send " + secret_validation_method + " request to " + alert .Validity_endpoint )
438445 continue
@@ -462,7 +469,7 @@ func verifyAlerts(alerts []Alert) (alertsOutput []Alert, err error) {
462469 } else {
463470 alert .Validity_boolean = false
464471 }
465- if provider == "github" && alert .Validity_boolean == false && host != "github.com" {
472+ if provider == "github" && ! alert .Validity_boolean && host != "github.com" {
466473 // also confirm validity with the provided GitHub Enterprise Server API:
467474 alert = checkEnterpriseServerAPI (alert , client , secret_validation_method , secret_validation_content_type )
468475 if alert .Validity_response_code == "200" {
@@ -510,7 +517,7 @@ func checkForExpectedBody(response *http.Response, expected_body_key string, exp
510517func checkEnterpriseServerAPI (alert Alert , client * http.Client , secret_validation_method string , secret_validation_content_type string ) (alertOutput Alert ) {
511518 enterprise_server_api_endpoint := "https://" + host + "/api/v3/"
512519 // create a new http request:
513- req , err := http .NewRequest ("GET" , enterprise_server_api_endpoint , nil )
520+ req , _ := http .NewRequest ("GET" , enterprise_server_api_endpoint , nil )
514521 req .Header .Set ("Authorization" , "Bearer " + alert .Secret )
515522 req .Header .Set ("Content-Type" , secret_validation_content_type )
516523 req .Header .Set ("User-Agent" , "gh-secret-scanning" )
@@ -572,3 +579,63 @@ func createIssuesForValidAlerts(alerts []Alert) (err error) {
572579 fmt .Println (Blue ("Created " + strconv .Itoa (issue_count ) + " issue(s)." ))
573580 return err
574581}
582+
583+ func checkSecretScanningSetting (repository string ) (secretScanningEnabled bool , err error ) {
584+ // create a new client for the request:
585+ var opts api.ClientOptions
586+ opts .Headers = map [string ]string {
587+ "User-Agent" : "gh-secret-scanning" ,
588+ }
589+ client , err := api .NewHTTPClient (opts )
590+ if err != nil {
591+ return false , fmt .Errorf ("unable to create HTTP client" )
592+ }
593+ // make a GET request to the repository API:
594+ response , err := client .Get ("https://api.github.com/repos/" + repository )
595+
596+ if err != nil {
597+ return false , fmt .Errorf ("unable to get repository information for " + repository )
598+ }
599+ defer response .Body .Close ()
600+
601+ // check if the response has a 200 status code:
602+ if response .StatusCode != http .StatusOK {
603+ return false , fmt .Errorf ("non-200 status code received: %d" , response .StatusCode )
604+ }
605+
606+ // parse the JSON response
607+ var result map [string ]interface {}
608+ if err := json .NewDecoder (response .Body ).Decode (& result ); err != nil {
609+ return false , fmt .Errorf ("unable to parse JSON response" )
610+ }
611+
612+ // navigate to the required fields
613+ securityAndAnalysis , ok := result ["security_and_analysis" ].(map [string ]interface {})
614+ if ! ok {
615+ return false , fmt .Errorf ("security_and_analysis field not found" )
616+ }
617+
618+ advancedSecurity , ok := securityAndAnalysis ["advanced_security" ].(map [string ]interface {})
619+ if ! ok {
620+ return false , fmt .Errorf ("advanced_security field not found" )
621+ }
622+
623+ status , ok := advancedSecurity ["status" ].(string )
624+ if ! ok || status != "enabled" {
625+ return false , fmt .Errorf ("Advanced Security is not enabled for " + repository + Yellow ("\n Enable GitHub Advanced Security for the repository here: https://github.com/" + repository + "/settings/security_analysis" ))
626+ }
627+
628+ secretScanning , ok := securityAndAnalysis ["secret_scanning" ].(map [string ]interface {})
629+ if ! ok {
630+ return false , fmt .Errorf ("secret_scanning field not found" )
631+ }
632+
633+ secretScanningStatus , ok := secretScanning ["status" ].(string )
634+ if ! ok || secretScanningStatus != "enabled" {
635+ return false , fmt .Errorf ("secret scanning is not enabled for " + repository + Yellow ("\n Enable secret scanning for the repository here: https://github.com/" + repository + "/settings/security_analysis" ))
636+ } else {
637+ secretScanningEnabled = true
638+ }
639+
640+ return secretScanningEnabled , nil
641+ }
0 commit comments