diff --git a/commands/scanpullrequest/scanpullrequest.go b/commands/scanpullrequest/scanpullrequest.go index 07a59fcfc..da2b34e49 100644 --- a/commands/scanpullrequest/scanpullrequest.go +++ b/commands/scanpullrequest/scanpullrequest.go @@ -82,7 +82,7 @@ func verifyGitHubFrogbotEnvironment(client vcsclient.VcsClient, repoConfig *util // a. Audit the dependencies of the source and the target branches. // b. Compare the vulnerabilities found in source and target branches, and show only the new vulnerabilities added by the pull request. // Otherwise, only the source branch is scanned and all found vulnerabilities are being displayed. -func scanPullRequest(repo *utils.Repository, client vcsclient.VcsClient) error { +func scanPullRequest(repo *utils.Repository, client vcsclient.VcsClient) (err error) { pullRequestDetails := repo.PullRequestDetails log.Info(fmt.Sprintf("Scanning Pull Request #%d (from source branch: <%s/%s/%s> to target branch: <%s/%s/%s>)", pullRequestDetails.ID, @@ -91,14 +91,27 @@ func scanPullRequest(repo *utils.Repository, client vcsclient.VcsClient) error { log.Info("-----------------------------------------------------------") // Audit PR code - vulnerabilitiesRows, iacRows, err := auditPullRequest(repo, client, pullRequestDetails) + vulnerabilitiesRows, iacRows, secretsRows, err := auditPullRequest(repo, client, pullRequestDetails) if err != nil { - return err + return + } + + shouldSendExposedSecretsEmail := len(secretsRows) > 0 && repo.SmtpServer != "" + if shouldSendExposedSecretsEmail { + prSourceDetails := pullRequestDetails.Source + secretsEmailDetails := utils.NewSecretsEmailDetails( + client, repo.GitProvider, + prSourceDetails.Owner, prSourceDetails.Repository, + prSourceDetails.Name, pullRequestDetails.URL, + secretsRows, repo.EmailDetails) + if err = utils.AlertSecretsExposed(secretsEmailDetails); err != nil { + return + } } // Delete previous Frogbot pull request message if exists if err = deleteExistingPullRequestComment(repo, client); err != nil { - return err + return } // Create a pull request message @@ -106,18 +119,19 @@ func scanPullRequest(repo *utils.Repository, client vcsclient.VcsClient) error { // Add comment to the pull request if err = client.AddPullRequestComment(context.Background(), repo.RepoOwner, repo.RepoName, message, int(pullRequestDetails.ID)); err != nil { - return errors.New("couldn't add pull request comment: " + err.Error()) + err = errors.New("couldn't add pull request comment: " + err.Error()) + return } // Fail the Frogbot task if a security issue is found and Frogbot isn't configured to avoid the failure. if repo.FailOnSecurityIssues != nil && *repo.FailOnSecurityIssues && len(vulnerabilitiesRows) > 0 { err = errors.New(securityIssueFoundErr) } - return err + return } // Downloads Pull Requests branches code and audits them -func auditPullRequest(repoConfig *utils.Repository, client vcsclient.VcsClient, pullRequestDetails vcsclient.PullRequestInfo) (vulnerabilitiesRows []formats.VulnerabilityOrViolationRow, iacRows []formats.IacSecretsRow, err error) { +func auditPullRequest(repoConfig *utils.Repository, client vcsclient.VcsClient, pullRequestDetails vcsclient.PullRequestInfo) (vulnerabilitiesRows []formats.VulnerabilityOrViolationRow, iacRows []formats.IacSecretsRow, secretsRows []formats.IacSecretsRow, err error) { // Download source branch sourceBranchInfo := pullRequestDetails.Source sourceBranchWd, cleanupSource, err := utils.DownloadRepoToTempDir(client, sourceBranchInfo.Owner, sourceBranchInfo.Repository, sourceBranchInfo.Name) @@ -157,8 +171,8 @@ func auditPullRequest(repoConfig *utils.Repository, client vcsclient.VcsClient, } // Set JAS output flags - extendedScanResults := sourceResults.ExtendedScanResults - repoConfig.OutputWriter.SetJasOutputFlags(extendedScanResults.EntitledForJas, len(extendedScanResults.ApplicabilityScanResults) > 0) + sourceScanResults := sourceResults.ExtendedScanResults + repoConfig.OutputWriter.SetJasOutputFlags(sourceScanResults.EntitledForJas, len(sourceScanResults.ApplicabilityScanResults) > 0) // Get all issues that were found in the source branch if repoConfig.IncludeAllVulnerabilities { @@ -169,7 +183,8 @@ func auditPullRequest(repoConfig *utils.Repository, client vcsclient.VcsClient, return } vulnerabilitiesRows = append(vulnerabilitiesRows, allIssuesRows...) - iacRows = append(iacRows, xrayutils.PrepareIacs(sourceResults.ExtendedScanResults.IacScanResults)...) + iacRows = append(iacRows, xrayutils.PrepareIacs(sourceScanResults.IacScanResults)...) + secretsRows = append(secretsRows, xrayutils.PrepareSecrets(sourceScanResults.SecretsScanResults)...) continue } @@ -180,35 +195,62 @@ func auditPullRequest(repoConfig *utils.Repository, client vcsclient.VcsClient, if err != nil { return } - var newIssuesRows []formats.VulnerabilityOrViolationRow - newIssuesRows, err = createNewIssuesRows(targetResults, sourceResults) - if err != nil { + + // Get new issues + var newVulnerabilities []formats.VulnerabilityOrViolationRow + var newIacs, newSecrets []formats.IacSecretsRow + if newVulnerabilities, newIacs, newSecrets, err = getNewIssues(targetResults, sourceResults); err != nil { return } - vulnerabilitiesRows = append(vulnerabilitiesRows, newIssuesRows...) - iacRows = append(iacRows, createNewIacRows(targetResults.ExtendedScanResults.IacScanResults, sourceResults.ExtendedScanResults.IacScanResults)...) + vulnerabilitiesRows = append(vulnerabilitiesRows, newVulnerabilities...) + iacRows = append(iacRows, newIacs...) + secretsRows = append(secretsRows, newSecrets...) } return } -func createNewIacRows(targetIacResults, sourceIacResults []xrayutils.IacOrSecretResult) []formats.IacSecretsRow { - targetIacRows := xrayutils.PrepareIacs(targetIacResults) - sourceIacRows := xrayutils.PrepareIacs(sourceIacResults) - targetIacVulnerabilitiesKeys := datastructures.MakeSet[string]() - for _, row := range targetIacRows { - targetIacVulnerabilitiesKeys.Add(row.File + row.Text) - } - var addedIacVulnerabilities []formats.IacSecretsRow - for _, row := range sourceIacRows { - if !targetIacVulnerabilitiesKeys.Exists(row.File + row.Text) { - addedIacVulnerabilities = append(addedIacVulnerabilities, row) +func getNewIssues(targetResults, sourceResults *audit.Results) ([]formats.VulnerabilityOrViolationRow, []formats.IacSecretsRow, []formats.IacSecretsRow, error) { + var newVulnerabilities []formats.VulnerabilityOrViolationRow + var err error + if len(sourceResults.ExtendedScanResults.XrayResults) > 0 { + if newVulnerabilities, err = createNewVulnerabilitiesRows(targetResults, sourceResults); err != nil { + return nil, nil, nil, err + } + } + + var newIacs []formats.IacSecretsRow + if len(sourceResults.ExtendedScanResults.IacScanResults) > 0 { + targetIacRows := xrayutils.PrepareIacs(targetResults.ExtendedScanResults.IacScanResults) + sourceIacRows := xrayutils.PrepareIacs(sourceResults.ExtendedScanResults.IacScanResults) + newIacs = createNewIacOrSecretsRows(targetIacRows, sourceIacRows) + } + + var newSecrets []formats.IacSecretsRow + if len(sourceResults.ExtendedScanResults.SecretsScanResults) > 0 { + targetSecretsRows := xrayutils.PrepareSecrets(targetResults.ExtendedScanResults.SecretsScanResults) + sourceSecretsRows := xrayutils.PrepareSecrets(sourceResults.ExtendedScanResults.SecretsScanResults) + newSecrets = createNewIacOrSecretsRows(targetSecretsRows, sourceSecretsRows) + } + + return newVulnerabilities, newIacs, newSecrets, nil +} + +func createNewIacOrSecretsRows(targetResults, sourceResults []formats.IacSecretsRow) []formats.IacSecretsRow { + targetIacOrSecretsVulnerabilitiesKeys := datastructures.MakeSet[string]() + for _, row := range targetResults { + targetIacOrSecretsVulnerabilitiesKeys.Add(row.File + row.Text) + } + var addedIacOrSecretsVulnerabilities []formats.IacSecretsRow + for _, row := range sourceResults { + if !targetIacOrSecretsVulnerabilitiesKeys.Exists(row.File + row.Text) { + addedIacOrSecretsVulnerabilities = append(addedIacOrSecretsVulnerabilities, row) } } - return addedIacVulnerabilities + return addedIacOrSecretsVulnerabilities } // Create vulnerabilities rows. The rows should contain only the new issues added by this PR -func createNewIssuesRows(targetResults, sourceResults *audit.Results) (vulnerabilitiesRows []formats.VulnerabilityOrViolationRow, err error) { +func createNewVulnerabilitiesRows(targetResults, sourceResults *audit.Results) (vulnerabilitiesRows []formats.VulnerabilityOrViolationRow, err error) { targetScanAggregatedResults := aggregateScanResults(targetResults.ExtendedScanResults.XrayResults) sourceScanAggregatedResults := aggregateScanResults(sourceResults.ExtendedScanResults.XrayResults) @@ -305,9 +347,12 @@ func createPullRequestMessage(vulnerabilitiesRows []formats.VulnerabilityOrViola func deleteExistingPullRequestComment(repository *utils.Repository, client vcsclient.VcsClient) error { log.Debug("Looking for an existing Frogbot pull request comment. Deleting it if it exists...") - comments, err := utils.GetSortedPullRequestComments(client, repository.RepoOwner, repository.RepoName, int(repository.PullRequestDetails.ID)) + prDetails := repository.PullRequestDetails + comments, err := utils.GetSortedPullRequestComments(client, prDetails.Target.Owner, prDetails.Target.Repository, int(prDetails.ID)) if err != nil { - return err + return fmt.Errorf( + "failed to get comments. the following details were used in order to fetch the comments: <%s/%s> pull request #%d. the error received: %s", + repository.RepoOwner, repository.RepoName, int(repository.PullRequestDetails.ID), err.Error()) } commentID := frogbotCommentNotFound @@ -320,7 +365,7 @@ func deleteExistingPullRequestComment(repository *utils.Repository, client vcscl } if commentID != frogbotCommentNotFound { - err = client.DeletePullRequestComment(context.Background(), repository.RepoOwner, repository.RepoName, int(repository.PullRequestDetails.ID), commentID) + err = client.DeletePullRequestComment(context.Background(), prDetails.Target.Owner, prDetails.Target.Repository, int(prDetails.ID), commentID) } return err diff --git a/commands/scanpullrequest/scanpullrequest_test.go b/commands/scanpullrequest/scanpullrequest_test.go index 04408fd61..2cd90932c 100644 --- a/commands/scanpullrequest/scanpullrequest_test.go +++ b/commands/scanpullrequest/scanpullrequest_test.go @@ -72,7 +72,7 @@ func TestCreateVulnerabilitiesRows(t *testing.T) { } // Run createNewIssuesRows and make sure that only the XRAY-2 violation exists in the results - rows, err := createNewIssuesRows( + rows, err := createNewVulnerabilitiesRows( &audit.Results{ExtendedScanResults: &utils2.ExtendedScanResults{XrayResults: []services.ScanResponse{previousScan}}}, &audit.Results{ExtendedScanResults: &utils2.ExtendedScanResults{XrayResults: []services.ScanResponse{currentScan}}}, ) @@ -128,7 +128,7 @@ func TestCreateVulnerabilitiesRowsCaseNoPrevViolations(t *testing.T) { } // Run createNewIssuesRows and expect both XRAY-1 and XRAY-2 violation in the results - rows, err := createNewIssuesRows( + rows, err := createNewVulnerabilitiesRows( &audit.Results{ExtendedScanResults: &utils2.ExtendedScanResults{XrayResults: []services.ScanResponse{previousScan}}}, &audit.Results{ExtendedScanResults: &utils2.ExtendedScanResults{XrayResults: []services.ScanResponse{currentScan}}}, ) @@ -163,7 +163,7 @@ func TestGetNewViolationsCaseNoNewViolations(t *testing.T) { } // Run createNewIssuesRows and expect no violations in the results - rows, err := createNewIssuesRows( + rows, err := createNewVulnerabilitiesRows( &audit.Results{ExtendedScanResults: &utils2.ExtendedScanResults{XrayResults: []services.ScanResponse{previousScan}}}, &audit.Results{ExtendedScanResults: &utils2.ExtendedScanResults{XrayResults: []services.ScanResponse{currentScan}}}, ) @@ -281,7 +281,7 @@ func TestGetNewVulnerabilities(t *testing.T) { } // Run createNewIssuesRows and make sure that only the XRAY-2 vulnerability exists in the results - rows, err := createNewIssuesRows( + rows, err := createNewVulnerabilitiesRows( &audit.Results{ExtendedScanResults: &utils2.ExtendedScanResults{XrayResults: []services.ScanResponse{previousScan}, EntitledForJas: true, ApplicabilityScanResults: map[string]string{"CVE-2023-4321": "Applicable"}}}, &audit.Results{ExtendedScanResults: &utils2.ExtendedScanResults{XrayResults: []services.ScanResponse{currentScan}, EntitledForJas: true, ApplicabilityScanResults: map[string]string{"CVE-2023-4321": "Applicable"}}}, ) @@ -334,7 +334,7 @@ func TestGetNewVulnerabilitiesCaseNoPrevVulnerabilities(t *testing.T) { } // Run createNewIssuesRows and expect both XRAY-1 and XRAY-2 vulnerability in the results - rows, err := createNewIssuesRows( + rows, err := createNewVulnerabilitiesRows( &audit.Results{ExtendedScanResults: &utils2.ExtendedScanResults{XrayResults: []services.ScanResponse{previousScan}}}, &audit.Results{ExtendedScanResults: &utils2.ExtendedScanResults{XrayResults: []services.ScanResponse{currentScan}}}, ) @@ -368,7 +368,7 @@ func TestGetNewVulnerabilitiesCaseNoNewVulnerabilities(t *testing.T) { } // Run createNewIssuesRows and expect no vulnerability in the results - rows, err := createNewIssuesRows( + rows, err := createNewVulnerabilitiesRows( &audit.Results{ExtendedScanResults: &utils2.ExtendedScanResults{XrayResults: []services.ScanResponse{previousScan}}}, &audit.Results{ExtendedScanResults: &utils2.ExtendedScanResults{XrayResults: []services.ScanResponse{currentScan}}}, ) @@ -683,8 +683,7 @@ func TestCreateNewIacRows(t *testing.T) { Severity: "High", File: "file1", LineColumn: "1:10", - Type: "Secret", - Text: "Sensitive information", + Text: "aws violation", }, }, sourceIacResults: []utils2.IacOrSecretResult{}, @@ -694,6 +693,73 @@ func TestCreateNewIacRows(t *testing.T) { name: "No vulnerabilities in target IaC results", targetIacResults: []utils2.IacOrSecretResult{}, sourceIacResults: []utils2.IacOrSecretResult{ + { + Severity: "High", + File: "file1", + LineColumn: "1:10", + Text: "aws violation", + }, + }, + expectedAddedIacVulnerabilities: []formats.IacSecretsRow{ + { + Severity: "High", + File: "file1", + LineColumn: "1:10", + Text: "aws violation", + SeverityNumValue: 10, + }, + }, + }, + { + name: "Some new vulnerabilities in source IaC results", + targetIacResults: []utils2.IacOrSecretResult{ + { + Severity: "High", + File: "file1", + LineColumn: "1:10", + Text: "aws violation", + }, + }, + sourceIacResults: []utils2.IacOrSecretResult{ + { + Severity: "Medium", + File: "file2", + LineColumn: "2:5", + Text: "gcp violation", + }, + }, + expectedAddedIacVulnerabilities: []formats.IacSecretsRow{ + { + Severity: "Medium", + SeverityNumValue: 8, + File: "file2", + LineColumn: "2:5", + Text: "gcp violation", + }, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + targetIacRows := utils2.PrepareSecrets(tc.targetIacResults) + sourceIacRows := utils2.PrepareSecrets(tc.sourceIacResults) + addedIacVulnerabilities := createNewIacOrSecretsRows(targetIacRows, sourceIacRows) + assert.ElementsMatch(t, tc.expectedAddedIacVulnerabilities, addedIacVulnerabilities) + }) + } +} + +func TestCreateNewSecretRows(t *testing.T) { + testCases := []struct { + name string + targetSecretsResults []utils2.IacOrSecretResult + sourceSecretsResults []utils2.IacOrSecretResult + expectedAddedSecretsVulnerabilities []formats.IacSecretsRow + }{ + { + name: "No vulnerabilities in source secrets results", + targetSecretsResults: []utils2.IacOrSecretResult{ { Severity: "High", File: "file1", @@ -702,7 +768,22 @@ func TestCreateNewIacRows(t *testing.T) { Text: "Sensitive information", }, }, - expectedAddedIacVulnerabilities: []formats.IacSecretsRow{ + sourceSecretsResults: []utils2.IacOrSecretResult{}, + expectedAddedSecretsVulnerabilities: []formats.IacSecretsRow{}, + }, + { + name: "No vulnerabilities in target secrets results", + targetSecretsResults: []utils2.IacOrSecretResult{}, + sourceSecretsResults: []utils2.IacOrSecretResult{ + { + Severity: "High", + File: "file1", + LineColumn: "1:10", + Type: "Secret", + Text: "Sensitive information", + }, + }, + expectedAddedSecretsVulnerabilities: []formats.IacSecretsRow{ { Severity: "High", File: "file1", @@ -714,8 +795,8 @@ func TestCreateNewIacRows(t *testing.T) { }, }, { - name: "Some new vulnerabilities in source IaC results", - targetIacResults: []utils2.IacOrSecretResult{ + name: "Some new vulnerabilities in source secrets results", + targetSecretsResults: []utils2.IacOrSecretResult{ { Severity: "High", File: "file1", @@ -724,7 +805,7 @@ func TestCreateNewIacRows(t *testing.T) { Text: "Sensitive information", }, }, - sourceIacResults: []utils2.IacOrSecretResult{ + sourceSecretsResults: []utils2.IacOrSecretResult{ { Severity: "Medium", File: "file2", @@ -733,7 +814,7 @@ func TestCreateNewIacRows(t *testing.T) { Text: "Confidential data", }, }, - expectedAddedIacVulnerabilities: []formats.IacSecretsRow{ + expectedAddedSecretsVulnerabilities: []formats.IacSecretsRow{ { Severity: "Medium", SeverityNumValue: 8, @@ -748,8 +829,10 @@ func TestCreateNewIacRows(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - addedIacVulnerabilities := createNewIacRows(tc.targetIacResults, tc.sourceIacResults) - assert.ElementsMatch(t, tc.expectedAddedIacVulnerabilities, addedIacVulnerabilities) + targetSecretsRows := utils2.PrepareSecrets(tc.targetSecretsResults) + sourceSecretsRows := utils2.PrepareSecrets(tc.sourceSecretsResults) + addedSecretsVulnerabilities := createNewIacOrSecretsRows(targetSecretsRows, sourceSecretsRows) + assert.ElementsMatch(t, tc.expectedAddedSecretsVulnerabilities, addedSecretsVulnerabilities) }) } } @@ -758,9 +841,10 @@ func TestDeletePreviousPullRequestMessages(t *testing.T) { repository := &utils.Repository{ Params: utils.Params{ Git: utils.Git{ - RepoName: "repo", - RepoOwner: "owner", - PullRequestDetails: vcsclient.PullRequestInfo{ID: 17}, + PullRequestDetails: vcsclient.PullRequestInfo{Target: vcsclient.BranchInfo{ + Repository: "repo", + Owner: "owner", + }, ID: 17}, }, }, OutputWriter: &outputwriter.StandardOutput{}, diff --git a/commands/utils/consts.go b/commands/utils/consts.go index d3a47b319..717b040ab 100644 --- a/commands/utils/consts.go +++ b/commands/utils/consts.go @@ -52,6 +52,13 @@ const ( FixableOnlyEnv = "JF_FIXABLE_ONLY" WatchesDelimiter = "," + // Email related environment variables + //#nosec G101 -- False positive - no hardcoded credentials. + SmtpPasswordEnv = "JF_SMTP_PASSWORD" + SmtpUserEnv = "JF_SMTP_USER" + SmtpServerEnv = "JF_SMTP_SERVER" + EmailReceiversEnv = "JF_EMAIL_RECEIVERS" + //#nosec G101 -- False positive - no hardcoded credentials. GitTokenEnv = "JF_GIT_TOKEN" GitBaseBranchEnv = "JF_GIT_BASE_BRANCH" @@ -75,7 +82,7 @@ const ( BranchNameTemplate = "frogbot-" + PackagePlaceHolder + "-" + BranchHashPlaceHolder AggregatedBranchNameTemplate = "frogbot-update-" + BranchHashPlaceHolder + "-dependencies" CommitMessageTemplate = "Upgrade " + PackagePlaceHolder + " to " + FixVersionPlaceHolder - PullRequestTitleTemplate = outputwriter.FrogbotPullRequestTitlePrefix + " Update version of " + PackagePlaceHolder + " to " + FixVersionPlaceHolder + PullRequestTitleTemplate = outputwriter.FrogbotTitlePrefix + " Update version of " + PackagePlaceHolder + " to " + FixVersionPlaceHolder // Frogbot Git author details showed in commits frogbotAuthorName = "JFrog-Frogbot" frogbotAuthorEmail = "eco-system+frogbot@jfrog.com" diff --git a/commands/utils/email.go b/commands/utils/email.go new file mode 100644 index 000000000..7164cc964 --- /dev/null +++ b/commands/utils/email.go @@ -0,0 +1,119 @@ +package utils + +import ( + "context" + "fmt" + "github.com/jfrog/frogbot/commands/utils/outputwriter" + "github.com/jfrog/froggit-go/vcsclient" + "github.com/jfrog/froggit-go/vcsutils" + "github.com/jfrog/gofrog/datastructures" + "github.com/jfrog/jfrog-cli-core/v2/xray/formats" + "github.com/jordan-wright/email" + "net/smtp" + "strings" +) + +var excludedEmailAddresses = []string{"no-reply", "no_reply", "noreply", "no.reply", "frogbot"} + +type SecretsEmailDetails struct { + gitClient vcsclient.VcsClient + gitProvider vcsutils.VcsProvider + branch string + repoName string + repoOwner string + detectedSecrets []formats.IacSecretsRow + pullRequestLink string + EmailDetails +} + +func NewSecretsEmailDetails(gitClient vcsclient.VcsClient, gitProvider vcsutils.VcsProvider, + repoOwner, repoName, branch, pullRequestLink string, + detectedSecrets []formats.IacSecretsRow, emailDetails EmailDetails) *SecretsEmailDetails { + return &SecretsEmailDetails{gitClient: gitClient, gitProvider: gitProvider, + repoOwner: repoOwner, repoName: repoName, branch: branch, pullRequestLink: pullRequestLink, + detectedSecrets: detectedSecrets, EmailDetails: emailDetails} +} + +func AlertSecretsExposed(secretsDetails *SecretsEmailDetails) (err error) { + if len(secretsDetails.detectedSecrets) == 0 { + return + } + var relevantEmailReceivers []string + if relevantEmailReceivers, err = getRelevantEmailReceivers(secretsDetails.gitClient, secretsDetails.repoOwner, secretsDetails.repoName, secretsDetails.branch, secretsDetails.EmailReceivers); err != nil { + return + } + secretsDetails.EmailReceivers = append(secretsDetails.EmailReceivers, relevantEmailReceivers...) + emailDetails := secretsDetails.EmailDetails + emailContent := getSecretsEmailContent(secretsDetails.detectedSecrets, secretsDetails.gitProvider, secretsDetails.pullRequestLink) + sender := fmt.Sprintf("JFrog Frogbot <%s>", emailDetails.SmtpUser) + subject := outputwriter.FrogbotTitlePrefix + " Frogbot detected potential secrets" + return sendEmail(sender, subject, emailContent, emailDetails) +} + +func getSecretsEmailContent(secrets []formats.IacSecretsRow, gitProvider vcsutils.VcsProvider, pullRequestLink string) string { + var tableContent strings.Builder + for _, secret := range secrets { + tableContent.WriteString( + fmt.Sprintf(outputwriter.SecretsEmailTableRow, + secret.File, + secret.LineColumn, + secret.Text)) + } + pullOrMergeRequest := "pull request" + if gitProvider == vcsutils.GitLab { + pullOrMergeRequest = "merge request" + } + + return fmt.Sprintf( + outputwriter.SecretsEmailHTMLTemplate, + outputwriter.SecretsEmailCSS, + pullRequestLink, + pullOrMergeRequest, + tableContent.String(), + ) +} + +func sendEmail(sender, subject, content string, emailDetails EmailDetails) error { + e := prepareEmail(sender, subject, content, emailDetails) + smtpAuth := smtp.PlainAuth("", emailDetails.SmtpUser, emailDetails.SmtpPassword, emailDetails.SmtpServer) + return e.Send(strings.Join([]string{emailDetails.SmtpServer, emailDetails.SmtpPort}, ":"), smtpAuth) +} + +func prepareEmail(sender, subject, content string, emailDetails EmailDetails) *email.Email { + e := email.NewEmail() + e.From = sender + e.To = emailDetails.EmailReceivers + e.Subject = subject + e.HTML = []byte(content) + return e +} + +func getRelevantEmailReceivers(client vcsclient.VcsClient, repoOwner, repoName, branch string, emailReceivers []string) ([]string, error) { + commits, err := client.GetCommits(context.Background(), repoOwner, repoName, branch) + if err != nil { + return nil, err + } + + return getEmailReceiversFromCommits(commits, emailReceivers) +} + +func getEmailReceiversFromCommits(commits []vcsclient.CommitInfo, preConfiguredEmailReceivers []string) ([]string, error) { + emailReceivers := datastructures.MakeSet[string]() + for _, commit := range commits { + if shouldExcludeEmailAddress(commit.AuthorEmail, excludedEmailAddresses) || shouldExcludeEmailAddress(commit.AuthorEmail, preConfiguredEmailReceivers) { + continue + } + emailReceivers.Add(commit.AuthorEmail) + } + + return emailReceivers.ToSlice(), nil +} + +func shouldExcludeEmailAddress(emailAddress string, excludes []string) bool { + for _, excludedEmailAddress := range excludes { + if strings.Contains(emailAddress, excludedEmailAddress) { + return true + } + } + return false +} diff --git a/commands/utils/email_test.go b/commands/utils/email_test.go new file mode 100644 index 000000000..4b01cb9da --- /dev/null +++ b/commands/utils/email_test.go @@ -0,0 +1,60 @@ +package utils + +import ( + "github.com/jfrog/frogbot/commands/utils/outputwriter" + "github.com/jfrog/froggit-go/vcsclient" + "github.com/jfrog/froggit-go/vcsutils" + "github.com/jfrog/jfrog-cli-core/v2/xray/formats" + "github.com/jordan-wright/email" + "github.com/stretchr/testify/assert" + "net/textproto" + "testing" +) + +func TestGetSecretsEmailContent(t *testing.T) { + secrets := []formats.IacSecretsRow{ + {Severity: "High", File: "/config.yaml", LineColumn: "12:30", Text: "pass*****"}, + {Severity: "Medium", File: "/server-conf.json", LineColumn: "15:20", Text: "pass*****"}, + } + // Test for results including the "Pull Request" keyword + expected := "\n\n\n\n Frogbot Secret Detection\n \n\n\n\t
\n\t\tThe following potential exposed secrets in your pull request have been detected by Frogbot\n\t\t
\n\t\t\n \n \n \n \n \n \n \n \n \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n \n
FILELINE:COLUMNSECRET
/config.yaml 12:30 pass*****
/server-conf.json 15:20 pass*****
\n\t\t
\n\t\tTo make Frogbot ignore the lines with the potential secrets, add a comment above the line which includes the jfrog-ignore keyword.\t\n\t\t
\n\t
\n\n" + actualContent := getSecretsEmailContent(secrets, vcsutils.GitHub, "https://github.com/owner/repo/pullrequest/1") + assert.Equal(t, expected, actualContent) + + // Test for results including the "Merge Request" keyword + expected = "\n\n\n\n Frogbot Secret Detection\n \n\n\n\t
\n\t\tThe following potential exposed secrets in your merge request have been detected by Frogbot\n\t\t
\n\t\t\n \n \n \n \n \n \n \n \n \n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n \n
FILELINE:COLUMNSECRET
/config.yaml 12:30 pass*****
/server-conf.json 15:20 pass*****
\n\t\t
\n\t\tTo make Frogbot ignore the lines with the potential secrets, add a comment above the line which includes the jfrog-ignore keyword.\t\n\t\t
\n\t
\n\n" + actualContent = getSecretsEmailContent(secrets, vcsutils.GitLab, "https://github.com/owner/repo/pullrequest/1") + assert.Equal(t, expected, actualContent) +} + +func TestPrepareEmail(t *testing.T) { + sender := "JFrog Frogbot " + subject := outputwriter.FrogbotTitlePrefix + " Frogbot detected potential secrets" + content := "content" + emailDetails := EmailDetails{EmailReceivers: []string{"receiver@jfrog.com"}} + expectedEmailObject := &email.Email{ + From: sender, + To: emailDetails.EmailReceivers, + Subject: subject, + HTML: []byte(content), + Headers: textproto.MIMEHeader{}, + } + actualEmailObject := prepareEmail(sender, subject, content, emailDetails) + assert.Equal(t, expectedEmailObject, actualEmailObject) +} + +func TestGetEmailReceiversFromCommits(t *testing.T) { + commits := []vcsclient.CommitInfo{ + {AuthorEmail: "test1@jfrog.com"}, + {AuthorEmail: "test2@jfrog.com"}, + {AuthorEmail: "receiver1@jfrog.com"}, + {AuthorEmail: "test3@jfrog.no.reply.com"}, + {AuthorEmail: "test3@jfrog.noreply.com"}, + {AuthorEmail: "test3@jfrog.no-reply.com"}, + {AuthorEmail: "test3@jfrog.frogbot.com"}, + } + preConfiguredEmailReceivers := []string{"receiver1@jfrog.com", "receiver2@jfrog.com"} + finalEmailReceiversList, err := getEmailReceiversFromCommits(commits, preConfiguredEmailReceivers) + assert.NoError(t, err) + assert.ElementsMatch(t, []string{"test1@jfrog.com", "test2@jfrog.com"}, finalEmailReceiversList) +} diff --git a/commands/utils/outputwriter/outputwriter.go b/commands/utils/outputwriter/outputwriter.go index b9ad57893..590d70329 100644 --- a/commands/utils/outputwriter/outputwriter.go +++ b/commands/utils/outputwriter/outputwriter.go @@ -10,11 +10,85 @@ import ( ) const ( - FrogbotPullRequestTitlePrefix = "[🐸 Frogbot]" + FrogbotTitlePrefix = "[🐸 Frogbot]" CommentGeneratedByFrogbot = "[JFrog Frogbot](https://github.com/jfrog/frogbot#readme)" vulnerabilitiesTableHeader = "\n| SEVERITY | DIRECT DEPENDENCIES | IMPACTED DEPENDENCY | FIXED VERSIONS |\n| :---------------------: | :----------------------------------: | :-----------------------------------: | :---------------------------------: |" vulnerabilitiesTableHeaderWithContextualAnalysis = "| SEVERITY | CONTEXTUAL ANALYSIS | DIRECT DEPENDENCIES | IMPACTED DEPENDENCY | FIXED VERSIONS |\n| :---------------------: | :----------------------------------: | :----------------------------------: | :-----------------------------------: | :---------------------------------: |" iacTableHeader = "\n| SEVERITY | FILE | LINE:COLUMN | FINDING |\n| :---------------------: | :----------------------------------: | :-----------------------------------: | :---------------------------------: |" + SecretsEmailCSS = `body { + font-family: Arial, sans-serif; + background-color: #f5f5f5; + } + table { + border-collapse: collapse; + width: 80%; + } + th, td { + padding: 10px; + border: 1px solid #ccc; + } + th { + background-color: #f2f2f2; + } + tr:nth-child(even) { + background-color: #f9f9f9; + } + tr:hover { + background-color: #f5f5f5; + } + .table-container { + max-width: 700px; + padding: 20px; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + border-radius: 10px; + overflow: hidden; + background-color: #fff; + margin-top: 10px; + } + .ignore-comments { + margin-top: 10px; + margin-bottom: 5px; + border-radius: 5px; + }` + //#nosec G101 -- full secrets would not be hard coded + SecretsEmailHTMLTemplate = ` + + + + Frogbot Secret Detection + + + +
+ The following potential exposed secrets in your %s have been detected by Frogbot +
+ + + + + + + + + + %s + +
FILELINE:COLUMNSECRET
+
+ To make Frogbot ignore the lines with the potential secrets, add a comment above the line which includes the jfrog-ignore keyword. +
+
+ +` + //#nosec G101 -- full secrets would not be hard coded + SecretsEmailTableRow = ` + + %s + %s + %s + ` ) // The OutputWriter interface allows Frogbot output to be written in an appropriate way for each git provider. @@ -123,9 +197,9 @@ func MarkdownComment(text string) string { func GetAggregatedPullRequestTitle(tech coreutils.Technology) string { if tech.ToString() == "" { - return FrogbotPullRequestTitlePrefix + " Update dependencies" + return FrogbotTitlePrefix + " Update dependencies" } - return fmt.Sprintf("%s Update %s dependencies", FrogbotPullRequestTitlePrefix, tech.ToFormal()) + return fmt.Sprintf("%s Update %s dependencies", FrogbotTitlePrefix, tech.ToFormal()) } func getVulnerabilitiesTableHeader(showCaColumn bool) string { diff --git a/commands/utils/outputwriter/simplifiedoutput.go b/commands/utils/outputwriter/simplifiedoutput.go index 1cd1085bf..688692b5f 100644 --- a/commands/utils/outputwriter/simplifiedoutput.go +++ b/commands/utils/outputwriter/simplifiedoutput.go @@ -46,10 +46,10 @@ func (smo *SimplifiedOutput) NoVulnerabilitiesTitle() string { } func (smo *SimplifiedOutput) VulnerabilitiesTitle(isComment bool) string { - if !isComment { - return GetSimplifiedTitle(VulnerabilitiesFixPrBannerSource) + if isComment { + return GetSimplifiedTitle(VulnerabilitiesPrBannerSource) } - return GetSimplifiedTitle(VulnerabilitiesPrBannerSource) + return GetSimplifiedTitle(VulnerabilitiesFixPrBannerSource) } func (smo *SimplifiedOutput) IsFrogbotResultComment(comment string) bool { diff --git a/commands/utils/outputwriter/standardoutput.go b/commands/utils/outputwriter/standardoutput.go index b5b1aa48c..c1833da1a 100644 --- a/commands/utils/outputwriter/standardoutput.go +++ b/commands/utils/outputwriter/standardoutput.go @@ -54,10 +54,10 @@ func (so *StandardOutput) VulnerabilitiesTitle(isComment bool) string { } func (so *StandardOutput) IsFrogbotResultComment(comment string) bool { - return strings.Contains(comment, GetIconTag(NoVulnerabilityPrBannerSource)) || - strings.Contains(comment, GetIconTag(VulnerabilitiesPrBannerSource)) || - strings.Contains(comment, GetIconTag(NoVulnerabilityMrBannerSource)) || - strings.Contains(comment, GetIconTag(VulnerabilitiesMrBannerSource)) + return strings.Contains(comment, string(NoVulnerabilityPrBannerSource)) || + strings.Contains(comment, string(VulnerabilitiesPrBannerSource)) || + strings.Contains(comment, string(NoVulnerabilityMrBannerSource)) || + strings.Contains(comment, string(VulnerabilitiesMrBannerSource)) } func (so *StandardOutput) SetVcsProvider(provider vcsutils.VcsProvider) { diff --git a/commands/utils/params.go b/commands/utils/params.go index 8ec6dfe01..79c160e7a 100644 --- a/commands/utils/params.go +++ b/commands/utils/params.go @@ -114,6 +114,41 @@ type Scan struct { FailOnSecurityIssues *bool `yaml:"failOnSecurityIssues,omitempty"` MinSeverity string `yaml:"minSeverity,omitempty"` Projects []Project `yaml:"projects,omitempty"` + EmailDetails `yaml:",inline"` +} + +type EmailDetails struct { + SmtpServer string + SmtpPort string + SmtpUser string + SmtpPassword string + EmailReceivers []string `yaml:"emailReceivers,omitempty"` +} + +func (s *Scan) SetEmailDetails() error { + smtpServerAndPort := getTrimmedEnv(SmtpServerEnv) + if smtpServerAndPort == "" { + return nil + } + splittedServerAndPort := strings.Split(smtpServerAndPort, ":") + if len(splittedServerAndPort) < 2 { + return fmt.Errorf("failed while setting your email details. Could not extract the smtp server and its port from the %s environment variable. Expected format: `smtp.server.com:port`, received: %s", SmtpServerEnv, smtpServerAndPort) + } + s.SmtpServer = splittedServerAndPort[0] + s.SmtpPort = splittedServerAndPort[1] + s.SmtpUser = getTrimmedEnv(SmtpUserEnv) + s.SmtpPassword = getTrimmedEnv(SmtpPasswordEnv) + if s.SmtpUser == "" { + return fmt.Errorf("failed while setting your email details. SMTP username is expected, but the %s environment variable is empty", SmtpUserEnv) + } + if s.SmtpPassword == "" { + return fmt.Errorf("failed while setting your email details. SMTP password is expected, but the %s environment variable is empty", SmtpPasswordEnv) + } + if len(s.EmailReceivers) == 0 { + emailReceivers := getTrimmedEnv(EmailReceiversEnv) + s.EmailReceivers = strings.Split(emailReceivers, ",") + } + return nil } func (s *Scan) setDefaultsIfNeeded() (err error) { @@ -151,6 +186,7 @@ func (s *Scan) setDefaultsIfNeeded() (err error) { return } } + err = s.SetEmailDetails() return } diff --git a/commands/utils/params_test.go b/commands/utils/params_test.go index 7b41ea54c..6c7b9cb10 100644 --- a/commands/utils/params_test.go +++ b/commands/utils/params_test.go @@ -1,6 +1,8 @@ package utils import ( + "errors" + "fmt" "github.com/jfrog/froggit-go/vcsclient" "github.com/jfrog/jfrog-cli-core/v2/utils/config" "os" @@ -528,3 +530,118 @@ func TestBuildMergedRepoAggregator(t *testing.T) { assert.Equal(t, []string{"restore"}, project.InstallCommandArgs) assert.False(t, *project.UseWrapper) } + +func TestSetEmailDetails(t *testing.T) { + tests := []struct { + name string + envs map[string]string + expectedError error + expectedServer string + expectedPort string + }{ + { + name: "ValidEmailDetails", + envs: map[string]string{ + SmtpServerEnv: "smtp.server.com:587", + SmtpUserEnv: "user", + SmtpPasswordEnv: "pass", + EmailReceiversEnv: "receiver1@example.com, receiver2@example.com", + }, + expectedError: nil, + expectedServer: "smtp.server.com", + expectedPort: "587", + }, + { + name: "MissingSmtpServer", + envs: map[string]string{ + SmtpUserEnv: "user", + SmtpPasswordEnv: "pass", + EmailReceiversEnv: "receiver1@example.com,receiver2@example.com", + }, + expectedError: nil, + }, + { + name: "InvalidSmtpServerFormat", + envs: map[string]string{ + SmtpServerEnv: "invalid_server", + SmtpUserEnv: "user", + SmtpPasswordEnv: "pass", + EmailReceiversEnv: "receiver1@example.com,receiver2@example.com", + }, + expectedError: errors.New("failed while setting your email details. Could not extract the smtp server and its port from the JF_SMTP_SERVER environment variable. Expected format: `smtp.server.com:port`, received: invalid_server"), + }, + { + name: "MissingSmtpAuthUser", + envs: map[string]string{ + SmtpServerEnv: "smtp.server.com:587", + SmtpPasswordEnv: "pass", + EmailReceiversEnv: "receiver1@example.com,receiver2@example.com", + }, + expectedError: fmt.Errorf("failed while setting your email details. SMTP username is expected, but the %s environment variable is empty", SmtpUserEnv), + }, + { + name: "MissingSmtpAuthPass", + envs: map[string]string{ + SmtpServerEnv: "smtp.server.com:587", + SmtpUserEnv: "user", + EmailReceiversEnv: "receiver1@example.com,receiver2@example.com", + }, + expectedError: fmt.Errorf("failed while setting your email details. SMTP password is expected, but the %s environment variable is empty", SmtpPasswordEnv), + }, + { + name: "EmptyEmailReceivers", + envs: map[string]string{ + SmtpServerEnv: "smtp.server.com:587", + SmtpUserEnv: "user", + SmtpPasswordEnv: "pass", + }, + expectedError: nil, + expectedServer: "smtp.server.com", + expectedPort: "587", + }, + { + name: "InvalidEmailReceivers", + envs: map[string]string{ + SmtpServerEnv: "smtp.server.com:587", + SmtpUserEnv: "user", + SmtpPasswordEnv: "pass", + EmailReceiversEnv: "receiver1@example.com,receiver2", + }, + expectedError: nil, + expectedServer: "smtp.server.com", + expectedPort: "587", + }, + { + name: "NoEmailDetails", + envs: map[string]string{}, + expectedError: fmt.Errorf("failed while setting your email details. SMTP username is expected, but the %s environment variable is empty", "SmtpAuthUserEnv"), + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + // Mock environment variables + originalEnvs := make(map[string]string) + for key, value := range test.envs { + originalEnvs[key] = os.Getenv(key) + assert.NoError(t, os.Setenv(key, value)) + } + defer func() { + for key, value := range originalEnvs { + assert.NoError(t, os.Setenv(key, value)) + } + }() + scan := &Scan{} + err := scan.SetEmailDetails() + + if err != nil { + assert.EqualError(t, test.expectedError, err.Error()) + } + + if err == nil { + assert.Equal(t, test.expectedServer, scan.SmtpServer) + assert.Equal(t, test.expectedPort, scan.SmtpPort) + } + }) + } +} diff --git a/docs/install-azure-pipelines.md b/docs/install-azure-pipelines.md index 460e32276..a55c20999 100644 --- a/docs/install-azure-pipelines.md +++ b/docs/install-azure-pipelines.md @@ -96,6 +96,19 @@ To install Frogbot on Azure Repos repositories, follow these steps. # Uncheck the 'Store Artifacts Locally' option # 3. Set the value of the 'JF_RELEASES_REPO' variable with the Repository Key you created. # JF_RELEASES_REPO: "" + + # [Optional] + # Configure the SMTP server to enable Frogbot to send emails with detected secrets in pull request scans. + # SMTP server URL including should the relevant port: (Example: smtp.server.com:8080) + # JF_SMTP_SERVER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The username required for authenticating with the SMTP server. + # JF_SMTP_USER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The password associated with the username required for authentication with the SMTP server. + # JF_SMTP_PASSWORD: "" ########################################################################## ## If your project uses a 'frogbot-config.yml' file, you can define ## @@ -184,6 +197,12 @@ To install Frogbot on Azure Repos repositories, follow these steps. # [Optional, Default: eco-system+frogbot@jfrog.com] # Set the email of the commit author # JF_GIT_EMAIL_AUTHOR: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # List of email addresses to receive emails about secrets that has been detected in a pull request scan. + # The list should be seperated by commas. + # JF_EMAIL_RECEIVERS: "" + displayName: 'Download and Run Frogbot' inputs: script: | diff --git a/docs/install-bitbucket-server.md b/docs/install-bitbucket-server.md index 4c9647f91..b36f527bc 100644 --- a/docs/install-bitbucket-server.md +++ b/docs/install-bitbucket-server.md @@ -30,196 +30,214 @@ - Save your Bitbucket access token as a Credential in Jenkins with the `FROGBOT_GIT_TOKEN` Credential ID. - Create a Jenkinsfile with the below template content, and push it to the root of one of your Git repositories. - In the Jenkinsfile, set the values of all the mandatory variables. - - In the Jenkinsfile, modify the code inside the `Download Frogbot` and `Scan Pull Requests` according to the Jenkins agent operating system. - - Create a Pipeline job in Jenkins pointing to the Jenkinsfile in your Git repository. + - In the Jenkinsfile, modify the code inside the `Download Frogbot` and `Scan Pull Requests` according to the Jenkins agent operating system. + - Create a Pipeline job in Jenkins pointing to the Jenkinsfile in your Git repository. -
- Template +
+ Template - ```groovy - // Run the job once an hour - CRON_SETTINGS = '''* */1 * * *''' - - pipeline { - agent any - - triggers { - cron(CRON_SETTINGS) - } - - environment { - // [Mandatory] - // JFrog platform URL (This functionality requires version 3.29.0 or above of Xray) - JF_URL= credentials("JF_URL") - - // [Mandatory if JF_USER and JF_PASSWORD are not provided] - // JFrog access token with 'read' permissions for Xray - JF_ACCESS_TOKEN= credentials("JF_ACCESS_TOKEN") - - // [Mandatory if JF_ACCESS_TOKEN is not provided] - // JFrog user and password with 'read' permissions for Xray - // JF_USER= credentials("JF_USER") - // JF_PASSWORD= credentials("JF_PASSWORD") - - // [Mandatory] - // Bitbucket access token with the write repository permissions - JF_GIT_TOKEN= credentials("FROGBOT_GIT_TOKEN") - JF_GIT_PROVIDER= "bitbucketServer" - - // [Mandatory] - // Username of the account associated with the token - JF_GIT_USERNAME= "" - - // [Mandatory] - // Bitbucket project namespace - // Private projects should start with the prefix: "~" - JF_GIT_OWNER= "" - - // [Mandatory] - // API endpoint to Bitbucket server - JF_GIT_API_ENDPOINT= "" - - // [Optional] - // By default, the Frogbot workflows download the Frogbot executable as well as other tools - // needed from https://releases.jfrog.io - // If the machine that runs Frogbot has no access to the internet, follow these steps to allow the - // executable to be downloaded from an Artifactory instance, which the machine has access to: - // - // 1. Login to the Artifactory UI, with a user who has admin credentials. - // 2. Create a Remote Repository with the following properties set. - // Under the 'Basic' tab: - // Package Type: Generic - // URL: https://releases.jfrog.io - // Under the 'Advanced' tab: - // Uncheck the 'Store Artifacts Locally' option - // 3. Set the value of the 'JF_RELEASES_REPO' variable with the Repository Key you created. - // JF_RELEASES_REPO= "" - - /////////////////////////////////////////////////////////////////////////// - // If your project uses a 'frogbot-config.yml' file, you should define // - // the following variables inside the file, instead of here. // - /////////////////////////////////////////////////////////////////////////// - - // [Mandatory] - // The name of the repository - JF_GIT_REPO= "" + ```groovy + // Run the job once an hour + CRON_SETTINGS = '''* */1 * * *''' + + pipeline { + agent any + + triggers { + cron(CRON_SETTINGS) + } + + environment { + // [Mandatory] + // JFrog platform URL (This functionality requires version 3.29.0 or above of Xray) + JF_URL= credentials("JF_URL") + + // [Mandatory if JF_USER and JF_PASSWORD are not provided] + // JFrog access token with 'read' permissions for Xray + JF_ACCESS_TOKEN= credentials("JF_ACCESS_TOKEN") + + // [Mandatory if JF_ACCESS_TOKEN is not provided] + // JFrog user and password with 'read' permissions for Xray + // JF_USER= credentials("JF_USER") + // JF_PASSWORD= credentials("JF_PASSWORD") + + // [Mandatory] + // Bitbucket access token with the write repository permissions + JF_GIT_TOKEN= credentials("FROGBOT_GIT_TOKEN") + JF_GIT_PROVIDER= "bitbucketServer" + + // [Mandatory] + // Username of the account associated with the token + JF_GIT_USERNAME= "" + + // [Mandatory] + // Bitbucket project namespace + // Private projects should start with the prefix: "~" + JF_GIT_OWNER= "" + + // [Mandatory] + // API endpoint to Bitbucket server + JF_GIT_API_ENDPOINT= "" + + // [Optional] + // By default, the Frogbot workflows download the Frogbot executable as well as other tools + // needed from https://releases.jfrog.io + // If the machine that runs Frogbot has no access to the internet, follow these steps to allow the + // executable to be downloaded from an Artifactory instance, which the machine has access to: + // + // 1. Login to the Artifactory UI, with a user who has admin credentials. + // 2. Create a Remote Repository with the following properties set. + // Under the 'Basic' tab: + // Package Type: Generic + // URL: https://releases.jfrog.io + // Under the 'Advanced' tab: + // Uncheck the 'Store Artifacts Locally' option + // 3. Set the value of the 'JF_RELEASES_REPO' variable with the Repository Key you created. + // JF_RELEASES_REPO= "" + + // [Optional] + // Configure the SMTP server to enable Frogbot to send emails with detected secrets in pull request scans. + // SMTP server URL including should the relevant port: (Example: smtp.server.com:8080) + // JF_SMTP_SERVER= "" + + // [Mandatory if JF_SMTP_SERVER is set] + // The username required for authenticating with the SMTP server. + // JF_SMTP_USER= "" + + // [Mandatory if JF_SMTP_SERVER is set] + // The password associated with the username required for authentication with the SMTP server. + // JF_SMTP_PASSWORD= "" + + /////////////////////////////////////////////////////////////////////////// + // If your project uses a 'frogbot-config.yml' file, you should define // + // the following variables inside the file, instead of here. // + /////////////////////////////////////////////////////////////////////////// + + // [Mandatory] + // The name of the repository + JF_GIT_REPO= "" + + // [Mandatory] + // The name of the branch on which Frogbot will perform the scan + JF_GIT_BASE_BRANCH= "" + + // [Mandatory if the two conditions below are met] + // 1. The project uses yarn 2, NuGet, or .NET to download its dependencies + // 2. The `installCommand` variable isn't set in your frogbot-config.yml file. + // + // The command that installs the project dependencies (e.g "nuget restore") + JF_INSTALL_DEPS_CMD= "" + + // [Optional, default: "."] + // Relative path to the root of the project in the Git repository + // JF_WORKING_DIR= path/to/project/dir + + // [Optional] + // Xray Watches. Learn more about them here: https://www.jfrog.com/confluence/display/JFROG/Configuring+Xray+Watches + // JF_WATCHES= ,... + + // [Optional] + // JFrog project. Learn more about it here: https://www.jfrog.com/confluence/display/JFROG/Projects + // JF_PROJECT= + + // [Optional, default: "FALSE"] + // Displays all existing vulnerabilities, including the ones that were added by the pull request. + // JF_INCLUDE_ALL_VULNERABILITIES= "TRUE" + + // [Optional, default: "TRUE"] + // Fails the Frogbot task if any security issue is found. + // JF_FAIL= "FALSE" + + // [Optional, default: "TRUE"] + // Relative path to a Pip requirements.txt file. If not set, the python project's dependencies are determined and scanned using the project setup.py file. + // JF_REQUIREMENTS_FILE= "" + + // [Optional, Default: "TRUE"] + // Use Gradle wrapper. + // JF_USE_WRAPPER= "FALSE" + + // [Optional] + // Frogbot will download the project dependencies if they're not cached locally. To download the + // dependencies from a virtual repository in Artifactory set the name of the repository. There's no + // need to set this value, if it is set in the frogbot-config.yml file. + // JF_DEPS_REPO= "" - // [Mandatory] - // The name of the branch on which Frogbot will perform the scan - JF_GIT_BASE_BRANCH= "" - - // [Mandatory if the two conditions below are met] - // 1. The project uses yarn 2, NuGet, or .NET to download its dependencies - // 2. The `installCommand` variable isn't set in your frogbot-config.yml file. - // - // The command that installs the project dependencies (e.g "nuget restore") - JF_INSTALL_DEPS_CMD= "" - - // [Optional, default: "."] - // Relative path to the root of the project in the Git repository - // JF_WORKING_DIR= path/to/project/dir - - // [Optional] - // Xray Watches. Learn more about them here: https://www.jfrog.com/confluence/display/JFROG/Configuring+Xray+Watches - // JF_WATCHES= ,... - - // [Optional] - // JFrog project. Learn more about it here: https://www.jfrog.com/confluence/display/JFROG/Projects - // JF_PROJECT= - - // [Optional, default: "FALSE"] - // Displays all existing vulnerabilities, including the ones that were added by the pull request. - // JF_INCLUDE_ALL_VULNERABILITIES= "TRUE" - - // [Optional, default: "TRUE"] - // Fails the Frogbot task if any security issue is found. - // JF_FAIL= "FALSE" - - // [Optional, default: "TRUE"] - // Relative path to a Pip requirements.txt file. If not set, the python project's dependencies are determined and scanned using the project setup.py file. - // JF_REQUIREMENTS_FILE= "" - - // [Optional, Default: "TRUE"] - // Use Gradle wrapper. - // JF_USE_WRAPPER= "FALSE" - - // [Optional] - // Frogbot will download the project dependencies if they're not cached locally. To download the - // dependencies from a virtual repository in Artifactory set the name of the repository. There's no - // need to set this value, if it is set in the frogbot-config.yml file. - // JF_DEPS_REPO= "" - - // [Optional] - // Template for the branch name generated by Frogbot when creating pull requests with fixes. - // The template must include ${BRANCH_NAME_HASH}, to ensure that the generated branch name is unique. - // The template can optionally include the ${IMPACTED_PACKAGE} and ${FIX_VERSION} variables. - // JF_BRANCH_NAME_TEMPLATE= "frogbot-${IMPACTED_PACKAGE}-${BRANCH_NAME_HASH}" - - // [Optional] - // Template for the commit message generated by Frogbot when creating pull requests with fixes - // The template can optionally include the ${IMPACTED_PACKAGE} and ${FIX_VERSION} variables. - // JF_COMMIT_MESSAGE_TEMPLATE= "Upgrade ${IMPACTED_PACKAGE} to ${FIX_VERSION}" - - // [Optional] - // Template for the pull request title generated by Frogbot when creating pull requests with fixes. - // The template can optionally include the ${IMPACTED_PACKAGE} and ${FIX_VERSION} variables. - // JF_PULL_REQUEST_TITLE_TEMPLATE= "[🐸 Frogbot] Upgrade ${IMPACTED_PACKAGE} to ${FIX_VERSION}" - - // [Optional, Default: "FALSE"] - // If TRUE, Frogbot creates a single pull request with all the fixes. - // If FALSE, Frogbot creates a separate pull request for each fix. - // JF_GIT_AGGREGATE_FIXES= "FALSE" - - // [Optional, Default: "FALSE"] - // Handle vulnerabilities with fix versions only - // JF_FIXABLE_ONLY= "TRUE" - - // [Optional] - // Set the minimum severity for vulnerabilities that should be fixed and commented on in pull requests - // The following values are accepted: Low, Medium, High, or Critical - // JF_MIN_SEVERITY= "" - - // [Optional, Default: eco-system+frogbot@jfrog.com] - // Set the email of the commit author - // JF_GIT_EMAIL_AUTHOR: "" - } + // [Optional] + // Template for the branch name generated by Frogbot when creating pull requests with fixes. + // The template must include ${BRANCH_NAME_HASH}, to ensure that the generated branch name is unique. + // The template can optionally include the ${IMPACTED_PACKAGE} and ${FIX_VERSION} variables. + // JF_BRANCH_NAME_TEMPLATE= "frogbot-${IMPACTED_PACKAGE}-${BRANCH_NAME_HASH}" + + // [Optional] + // Template for the commit message generated by Frogbot when creating pull requests with fixes + // The template can optionally include the ${IMPACTED_PACKAGE} and ${FIX_VERSION} variables. + // JF_COMMIT_MESSAGE_TEMPLATE= "Upgrade ${IMPACTED_PACKAGE} to ${FIX_VERSION}" + + // [Optional] + // Template for the pull request title generated by Frogbot when creating pull requests with fixes. + // The template can optionally include the ${IMPACTED_PACKAGE} and ${FIX_VERSION} variables. + // JF_PULL_REQUEST_TITLE_TEMPLATE= "[🐸 Frogbot] Upgrade ${IMPACTED_PACKAGE} to ${FIX_VERSION}" + + // [Optional, Default: "FALSE"] + // If TRUE, Frogbot creates a single pull request with all the fixes. + // If FALSE, Frogbot creates a separate pull request for each fix. + // JF_GIT_AGGREGATE_FIXES= "FALSE" + + // [Optional, Default: "FALSE"] + // Handle vulnerabilities with fix versions only + // JF_FIXABLE_ONLY= "TRUE" + + // [Optional] + // Set the minimum severity for vulnerabilities that should be fixed and commented on in pull requests + // The following values are accepted: Low, Medium, High, or Critical + // JF_MIN_SEVERITY= "" - stages { - stage('Download Frogbot') { - steps { - if (env.JF_RELEASES_REPO == "") { - // For Linux / MacOS runner: - sh """ curl -fLg "https://releases.jfrog.io/artifactory/frogbot/v2/[RELEASE]/getFrogbot.sh" | sh""" - // For Windows runner: - // powershell """iwr https://releases.jfrog.io/artifactory/frogbot/v2/[RELEASE]/frogbot-windows-amd64/frogbot.exe -OutFile .\frogbot.exe""" - } else { - // For Linux / MacOS air-gapped environments: - sh """ curl -fLg "${env.JF_URL}/artifactory/${env.JF_RELEASES_REPO}/artifactory/frogbot/v2/[RELEASE]/getFrogbot.sh" | sh""" - // For Windows air-gapped environments: - // powershell """iwr ${env.JF_URL}/artifactory/${env.JF_RELEASES_REPO}/artifactory/frogbot/v2/[RELEASE]/frogbot-windows-amd64/frogbot.exe -OutFile .\frogbot.exe""" - } + // [Optional, Default: eco-system+frogbot@jfrog.com] + // Set the email of the commit author + // JF_GIT_EMAIL_AUTHOR: "" + + // [Mandatory if JF_SMTP_SERVER is set] + // List of email addresses to receive emails about secrets that has been detected in a pull request scan. + // The list should be seperated by commas. + // JF_EMAIL_RECEIVERS: "" } - } - - stage('Scan Pull Requests') { - steps { - sh "./frogbot scan-all-pull-requests" - - // For Windows runner: - // powershell """.\frogbot.exe scan-all-pull-requests""" - } - } - - stage('Scan and Fix Repos') { - steps { - sh "./frogbot scan-multiple-repositories" - - // For Windows runner: - // powershell """.\frogbot.exe scan-multiple-repositories""" + + stages { + stage('Download Frogbot') { + steps { + if (env.JF_RELEASES_REPO == "") { + // For Linux / MacOS runner: + sh """ curl -fLg "https://releases.jfrog.io/artifactory/frogbot/v2/[RELEASE]/getFrogbot.sh" | sh""" + // For Windows runner: + // powershell """iwr https://releases.jfrog.io/artifactory/frogbot/v2/[RELEASE]/frogbot-windows-amd64/frogbot.exe -OutFile .\frogbot.exe""" + } else { + // For Linux / MacOS air-gapped environments: + sh """ curl -fLg "${env.JF_URL}/artifactory/${env.JF_RELEASES_REPO}/artifactory/frogbot/v2/[RELEASE]/getFrogbot.sh" | sh""" + // For Windows air-gapped environments: + // powershell """iwr ${env.JF_URL}/artifactory/${env.JF_RELEASES_REPO}/artifactory/frogbot/v2/[RELEASE]/frogbot-windows-amd64/frogbot.exe -OutFile .\frogbot.exe""" + } + } + } + + stage('Scan Pull Requests') { + steps { + sh "./frogbot scan-all-pull-requests" + + // For Windows runner: + // powershell """.\frogbot.exe scan-all-pull-requests""" + } + } + + stage('Scan and Fix Repos') { + steps { + sh "./frogbot scan-multiple-repositories" + + // For Windows runner: + // powershell """.\frogbot.exe scan-multiple-repositories""" + } + } } } - } - }
diff --git a/docs/install-gitlab.md b/docs/install-gitlab.md index 93c009bef..837c862cd 100644 --- a/docs/install-gitlab.md +++ b/docs/install-gitlab.md @@ -68,7 +68,20 @@ frogbot-scan: # Uncheck the 'Store Artifacts Locally' option # 3. Set the value of the 'JF_RELEASES_REPO' variable with the Repository Key you created. # JF_RELEASES_REPO: "" - + + # [Optional] + # Configure the SMTP server to enable Frogbot to send emails with detected secrets in pull request scans. + # SMTP server URL including should the relevant port: (Example: smtp.server.com:8080) + # JF_SMTP_SERVER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The username required for authenticating with the SMTP server. + # JF_SMTP_USER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The password associated with the username required for authentication with the SMTP server. + # JF_SMTP_PASSWORD: "" + ########################################################################### ## If your project uses a 'frogbot-config.yml' file, you should define ## ## the following variables inside the file, instead of here. ## @@ -148,6 +161,12 @@ frogbot-scan: # [Optional, Default: eco-system+frogbot@jfrog.com] # Set the email of the commit author # JF_GIT_EMAIL_AUTHOR: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # List of email addresses to receive emails about secrets that has been detected in a pull request scan. + # The list should be seperated by commas. + # JF_EMAIL_RECEIVERS: "" + script: # For Linux / MacOS runner: - | diff --git a/docs/templates/.frogbot/frogbot-config.yml b/docs/templates/.frogbot/frogbot-config.yml index 919ca12a3..9dfffd8c5 100644 --- a/docs/templates/.frogbot/frogbot-config.yml +++ b/docs/templates/.frogbot/frogbot-config.yml @@ -57,6 +57,12 @@ # The following values are accepted: Low, Medium, High or Critical # minSeverity: "" + # [Optional] + # List of email addresses to receive emails about secrets that has been detected in a pull request scan. + # Applies only to servers that are entitled to JFrog Advanced Security. + # emailReceivers: + # - user@company.com + # List of subprojects / project dirs inside the Git repository projects: # [Mandatory if the two conditions below are met] diff --git a/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-dotnet.yml b/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-dotnet.yml index cd44451c0..31ce5ff27 100644 --- a/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-dotnet.yml +++ b/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-dotnet.yml @@ -59,6 +59,19 @@ jobs: # 3. Set the value of the 'JF_RELEASES_REPO' variable with the Repository Key you created. # JF_RELEASES_REPO: "" + # [Optional] + # Configure the SMTP server to enable Frogbot to send emails with detected secrets in pull request scans. + # SMTP server URL including should the relevant port: (Example: smtp.server.com:8080) + # JF_SMTP_SERVER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The username required for authenticating with the SMTP server. + # JF_SMTP_USER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The password associated with the username required for authentication with the SMTP server. + # JF_SMTP_PASSWORD: "" + ########################################################################## ## If your project uses a 'frogbot-config.yml' file, you can define ## ## the following variables inside the file, instead of here. ## @@ -110,3 +123,8 @@ jobs: # Set the minimum severity for vulnerabilities that should be fixed and commented on in pull requests # The following values are accepted: Low, Medium, High or Critical # JF_MIN_SEVERITY: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # List of email addresses to receive emails about secrets that has been detected in a pull request scan. + # The list should be seperated by commas. + # JF_EMAIL_RECEIVERS: "" \ No newline at end of file diff --git a/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-go.yml b/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-go.yml index ab92eb46d..f6af9cad7 100644 --- a/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-go.yml +++ b/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-go.yml @@ -60,6 +60,19 @@ jobs: # 3. Set the value of the 'JF_RELEASES_REPO' variable with the Repository Key you created. # JF_RELEASES_REPO: "" + # [Optional] + # Configure the SMTP server to enable Frogbot to send emails with detected secrets in pull request scans. + # SMTP server URL including should the relevant port: (Example: smtp.server.com:8080) + # JF_SMTP_SERVER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The username required for authenticating with the SMTP server. + # JF_SMTP_USER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The password associated with the username required for authentication with the SMTP server. + # JF_SMTP_PASSWORD: "" + ########################################################################## ## If your project uses a 'frogbot-config.yml' file, you can define ## ## the following variables inside the file, instead of here. ## @@ -104,3 +117,8 @@ jobs: # Set the minimum severity for vulnerabilities that should be fixed and commented on in pull requests # The following values are accepted: Low, Medium, High or Critical # JF_MIN_SEVERITY: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # List of email addresses to receive emails about secrets that has been detected in a pull request scan. + # The list should be seperated by commas. + # JF_EMAIL_RECEIVERS: "" diff --git a/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-gradle.yml b/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-gradle.yml index d5050f1fa..729e20331 100644 --- a/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-gradle.yml +++ b/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-gradle.yml @@ -64,6 +64,19 @@ jobs: # 3. Set the value of the 'JF_RELEASES_REPO' variable with the Repository Key you created. # JF_RELEASES_REPO: "" + # [Optional] + # Configure the SMTP server to enable Frogbot to send emails with detected secrets in pull request scans. + # SMTP server URL including should the relevant port: (Example: smtp.server.com:8080) + # JF_SMTP_SERVER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The username required for authenticating with the SMTP server. + # JF_SMTP_USER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The password associated with the username required for authentication with the SMTP server. + # JF_SMTP_PASSWORD: "" + ########################################################################## ## If your project uses a 'frogbot-config.yml' file, you can define ## ## the following variables inside the file, instead of here. ## @@ -108,3 +121,8 @@ jobs: # Set the minimum severity for vulnerabilities that should be fixed and commented on in pull requests # The following values are accepted: Low, Medium, High or Critical # JF_MIN_SEVERITY: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # List of email addresses to receive emails about secrets that has been detected in a pull request scan. + # The list should be seperated by commas. + # JF_EMAIL_RECEIVERS: "" diff --git a/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-maven.yml b/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-maven.yml index d5894357d..409a18aa3 100644 --- a/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-maven.yml +++ b/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-maven.yml @@ -61,6 +61,19 @@ jobs: # 3. Set the value of the 'JF_RELEASES_REPO' variable with the Repository Key you created. # JF_RELEASES_REPO: "" + # [Optional] + # Configure the SMTP server to enable Frogbot to send emails with detected secrets in pull request scans. + # SMTP server URL including should the relevant port: (Example: smtp.server.com:8080) + # JF_SMTP_SERVER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The username required for authenticating with the SMTP server. + # JF_SMTP_USER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The password associated with the username required for authentication with the SMTP server. + # JF_SMTP_PASSWORD: "" + ########################################################################## ## If your project uses a 'frogbot-config.yml' file, you can define ## ## the following variables inside the file, instead of here. ## @@ -105,3 +118,8 @@ jobs: # Set the minimum severity for vulnerabilities that should be fixed and commented on in pull requests # The following values are accepted: Low, Medium, High or Critical # JF_MIN_SEVERITY: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # List of email addresses to receive emails about secrets that has been detected in a pull request scan. + # The list should be seperated by commas. + # JF_EMAIL_RECEIVERS: "" diff --git a/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-npm.yml b/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-npm.yml index 045958c49..8fc9c5dda 100644 --- a/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-npm.yml +++ b/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-npm.yml @@ -60,6 +60,24 @@ jobs: # 3. Set the value of the 'JF_RELEASES_REPO' variable with the Repository Key you created. # JF_RELEASES_REPO: "" + # [Optional] + # Set the minimum severity for vulnerabilities that should be fixed and commented on in pull requests + # The following values are accepted: Low, Medium, High or Critical + # JF_MIN_SEVERITY: "" + + # [Optional] + # Configure the SMTP server to enable Frogbot to send emails with detected secrets in pull request scans. + # SMTP server URL including should the relevant port: (Example: smtp.server.com:8080) + # JF_SMTP_SERVER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The username required for authenticating with the SMTP server. + # JF_SMTP_USER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The password associated with the username required for authentication with the SMTP server. + # JF_SMTP_PASSWORD: "" + ########################################################################### ## If your project uses a 'frogbot-config.yml' file, you can define ## ## the following variables inside the file, instead of here. ## @@ -107,7 +125,7 @@ jobs: # Handle vulnerabilities with fix versions only # JF_FIXABLE_ONLY: "TRUE" - # [Optional] - # Set the minimum severity for vulnerabilities that should be fixed and commented on in pull requests - # The following values are accepted: Low, Medium, High or Critical - # JF_MIN_SEVERITY: "" + # [Mandatory if JF_SMTP_SERVER is set] + # List of email addresses to receive emails about secrets that has been detected in a pull request scan. + # The list should be seperated by commas. + # JF_EMAIL_RECEIVERS: "" diff --git a/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-nuget.yml b/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-nuget.yml index 6209124aa..ba905c67b 100644 --- a/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-nuget.yml +++ b/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-nuget.yml @@ -59,6 +59,19 @@ jobs: # 3. Set the value of the 'JF_RELEASES_REPO' variable with the Repository Key you created. # JF_RELEASES_REPO: "" + # [Optional] + # Configure the SMTP server to enable Frogbot to send emails with detected secrets in pull request scans. + # SMTP server URL including should the relevant port: (Example: smtp.server.com:8080) + # JF_SMTP_SERVER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The username required for authenticating with the SMTP server. + # JF_SMTP_USER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The password associated with the username required for authentication with the SMTP server. + # JF_SMTP_PASSWORD: "" + ########################################################################## ## If your project uses a 'frogbot-config.yml' file, you can define ## ## the following variables inside the file, instead of here. ## @@ -110,3 +123,8 @@ jobs: # Set the minimum severity for vulnerabilities that should be fixed and commented on in pull requests # The following values are accepted: Low, Medium, High or Critical # JF_MIN_SEVERITY: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # List of email addresses to receive emails about secrets that has been detected in a pull request scan. + # The list should be seperated by commas. + # JF_EMAIL_RECEIVERS: "" \ No newline at end of file diff --git a/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-pip.yml b/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-pip.yml index 7828395fe..ea1871fc7 100644 --- a/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-pip.yml +++ b/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-pip.yml @@ -59,6 +59,19 @@ jobs: # 3. Set the value of the 'JF_RELEASES_REPO' variable with the Repository Key you created. # JF_RELEASES_REPO: "" + # [Optional] + # Configure the SMTP server to enable Frogbot to send emails with detected secrets in pull request scans. + # SMTP server URL including should the relevant port: (Example: smtp.server.com:8080) + # JF_SMTP_SERVER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The username required for authenticating with the SMTP server. + # JF_SMTP_USER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The password associated with the username required for authentication with the SMTP server. + # JF_SMTP_PASSWORD: "" + ########################################################################## ## If your project uses a 'frogbot-config.yml' file, you can define ## ## the following variables inside the file, instead of here. ## @@ -107,3 +120,8 @@ jobs: # Set the minimum severity for vulnerabilities that should be fixed and commented on in pull requests # The following values are accepted: Low, Medium, High or Critical # JF_MIN_SEVERITY: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # List of email addresses to receive emails about secrets that has been detected in a pull request scan. + # The list should be seperated by commas. + # JF_EMAIL_RECEIVERS: "" \ No newline at end of file diff --git a/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-pipenv.yml b/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-pipenv.yml index 225a67d62..e34ee2f4f 100644 --- a/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-pipenv.yml +++ b/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-pipenv.yml @@ -61,6 +61,19 @@ jobs: # 3. Set the value of the 'JF_RELEASES_REPO' variable with the Repository Key you created. # JF_RELEASES_REPO: "" + # [Optional] + # Configure the SMTP server to enable Frogbot to send emails with detected secrets in pull request scans. + # SMTP server URL including should the relevant port: (Example: smtp.server.com:8080) + # JF_SMTP_SERVER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The username required for authenticating with the SMTP server. + # JF_SMTP_USER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The password associated with the username required for authentication with the SMTP server. + # JF_SMTP_PASSWORD: "" + ########################################################################## ## If your project uses a 'frogbot-config.yml' file, you can define ## ## the following variables inside the file, instead of here. ## @@ -109,3 +122,8 @@ jobs: # Set the minimum severity for vulnerabilities that should be fixed and commented on in pull requests # The following values are accepted: Low, Medium, High or Critical # JF_MIN_SEVERITY: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # List of email addresses to receive emails about secrets that has been detected in a pull request scan. + # The list should be seperated by commas. + # JF_EMAIL_RECEIVERS: "" \ No newline at end of file diff --git a/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-poetry.yml b/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-poetry.yml index c7fed59e7..936d6c76a 100644 --- a/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-poetry.yml +++ b/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-poetry.yml @@ -61,6 +61,19 @@ jobs: # 3. Set the value of the 'JF_RELEASES_REPO' variable with the Repository Key you created. # JF_RELEASES_REPO: "" + # [Optional] + # Configure the SMTP server to enable Frogbot to send emails with detected secrets in pull request scans. + # SMTP server URL including should the relevant port: (Example: smtp.server.com:8080) + # JF_SMTP_SERVER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The username required for authenticating with the SMTP server. + # JF_SMTP_USER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The password associated with the username required for authentication with the SMTP server. + # JF_SMTP_PASSWORD: "" + ########################################################################## ## If your project uses a 'frogbot-config.yml' file, you can define ## ## the following variables inside the file, instead of here. ## @@ -105,3 +118,8 @@ jobs: # Set the minimum severity for vulnerabilities that should be fixed and commented on in pull requests # The following values are accepted: Low, Medium, High or Critical # JF_MIN_SEVERITY: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # List of email addresses to receive emails about secrets that has been detected in a pull request scan. + # The list should be seperated by commas. + # JF_EMAIL_RECEIVERS: "" \ No newline at end of file diff --git a/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-yarn.yml b/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-yarn.yml index 15a164145..b0b518a42 100644 --- a/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-yarn.yml +++ b/docs/templates/github-actions/scan-pull-request/frogbot-scan-pr-yarn.yml @@ -60,6 +60,19 @@ jobs: # 3. Set the value of the 'JF_RELEASES_REPO' variable with the Repository Key you created. # JF_RELEASES_REPO: "" + # [Optional] + # Configure the SMTP server to enable Frogbot to send emails with detected secrets in pull request scans. + # SMTP server URL including should the relevant port: (Example: smtp.server.com:8080) + # JF_SMTP_SERVER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The username required for authenticating with the SMTP server. + # JF_SMTP_USER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The password associated with the username required for authentication with the SMTP server. + # JF_SMTP_PASSWORD: "" + ########################################################################## ## If your project uses a 'frogbot-config.yml' file, you can define ## ## the following variables inside the file, instead of here. ## @@ -111,3 +124,8 @@ jobs: # Set the minimum severity for vulnerabilities that should be fixed and commented on in pull requests # The following values are accepted: Low, Medium, High or Critical # JF_MIN_SEVERITY: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # List of email addresses to receive emails about secrets that has been detected in a pull request scan. + # The list should be seperated by commas. + # JF_EMAIL_RECEIVERS: "" \ No newline at end of file diff --git a/docs/templates/jenkins/scan-pull-request.jenkinsfile b/docs/templates/jenkins/scan-pull-request.jenkinsfile index b522d7217..83644df08 100644 --- a/docs/templates/jenkins/scan-pull-request.jenkinsfile +++ b/docs/templates/jenkins/scan-pull-request.jenkinsfile @@ -66,6 +66,19 @@ pipeline { // The 'frogbot' executable and other tools it needs will be downloaded through this repository. // JF_RELEASES_REPO= "" + // [Optional] + // Configure the SMTP server to enable Frogbot to send emails with detected secrets in pull request scans. + // SMTP server URL including should the relevant port: (Example: smtp.server.com:8080) + // JF_SMTP_SERVER= "" + + // [Mandatory if JF_SMTP_SERVER is set] + // The username required for authenticating with the SMTP server. + // JF_SMTP_USER= "" + + // [Mandatory if JF_SMTP_SERVER is set] + // The password associated with the username required for authentication with the SMTP server. + // JF_SMTP_PASSWORD= "" + /////////////////////////////////////////////////////////////////////////// // If your project uses a 'frogbot-config.yml' file, you should define // // the following variables inside the file, instead of here. // @@ -144,7 +157,12 @@ pipeline { // [Optional, Default: eco-system+frogbot@jfrog.com] // Set the email of the commit author - // JF_GIT_EMAIL_AUTHOR: "" + // JF_GIT_EMAIL_AUTHOR= "" + + // [Mandatory if JF_SMTP_SERVER is set] + // List of email addresses to receive emails about secrets that has been detected in a pull request scan. + // The list should be seperated by commas. + // JF_EMAIL_RECEIVERS: "" } stages { diff --git a/docs/templates/jfrog-pipelines/pipelines-dotnet.yml b/docs/templates/jfrog-pipelines/pipelines-dotnet.yml index a12d24b6c..969f1b8a9 100644 --- a/docs/templates/jfrog-pipelines/pipelines-dotnet.yml +++ b/docs/templates/jfrog-pipelines/pipelines-dotnet.yml @@ -77,6 +77,19 @@ pipelines: # 3. Set the value of the 'JF_RELEASES_REPO' variable with the Repository Key you created. # JF_RELEASES_REPO: "" + # [Optional] + # Configure the SMTP server to enable Frogbot to send emails with detected secrets in pull request scans. + # SMTP server URL including should the relevant port: (Example: smtp.server.com:8080) + # JF_SMTP_SERVER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The username required for authenticating with the SMTP server. + # JF_SMTP_USER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The password associated with the username required for authentication with the SMTP server. + # JF_SMTP_PASSWORD: "" + ########################################################################### ## If your project uses a 'frogbot-config.yml' file, you should define ## ## the following variables inside the file, instead of here. ## @@ -160,6 +173,10 @@ pipelines: # Set the email of the commit author # JF_GIT_EMAIL_AUTHOR: "" + # [Mandatory if JF_SMTP_SERVER is set] + # List of email addresses to receive emails about secrets that has been detected in a pull request scan. + # The list should be seperated by commas. + # JF_EMAIL_RECEIVERS: "" execution: onExecute: - cd $res_frogbotGitRepo_resourcePath diff --git a/docs/templates/jfrog-pipelines/pipelines-go.yml b/docs/templates/jfrog-pipelines/pipelines-go.yml index 1967837f4..a33c5f693 100644 --- a/docs/templates/jfrog-pipelines/pipelines-go.yml +++ b/docs/templates/jfrog-pipelines/pipelines-go.yml @@ -77,6 +77,19 @@ pipelines: # 3. Set the value of the 'JF_RELEASES_REPO' variable with the Repository Key you created. # JF_RELEASES_REPO: "" + # [Optional] + # Configure the SMTP server to enable Frogbot to send emails with detected secrets in pull request scans. + # SMTP server URL including should the relevant port: (Example: smtp.server.com:8080) + # JF_SMTP_SERVER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The username required for authenticating with the SMTP server. + # JF_SMTP_USER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The password associated with the username required for authentication with the SMTP server. + # JF_SMTP_PASSWORD: "" + ########################################################################### ## If your project uses a 'frogbot-config.yml' file, you should define ## ## the following variables inside the file, instead of here. ## @@ -161,6 +174,10 @@ pipelines: # Set the email of the commit author # JF_GIT_EMAIL_AUTHOR: "" + # [Mandatory if JF_SMTP_SERVER is set] + # List of email addresses to receive emails about secrets that has been detected in a pull request scan. + # The list should be seperated by commas. + # JF_EMAIL_RECEIVERS: "" execution: onExecute: - cd $res_frogbotGitRepo_resourcePath diff --git a/docs/templates/jfrog-pipelines/pipelines-gradle.yml b/docs/templates/jfrog-pipelines/pipelines-gradle.yml index 329af6f85..3b68d248e 100644 --- a/docs/templates/jfrog-pipelines/pipelines-gradle.yml +++ b/docs/templates/jfrog-pipelines/pipelines-gradle.yml @@ -77,6 +77,19 @@ pipelines: # 3. Set the value of the 'JF_RELEASES_REPO' variable with the Repository Key you created. # JF_RELEASES_REPO: "" + # [Optional] + # Configure the SMTP server to enable Frogbot to send emails with detected secrets in pull request scans. + # SMTP server URL including should the relevant port: (Example: smtp.server.com:8080) + # JF_SMTP_SERVER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The username required for authenticating with the SMTP server. + # JF_SMTP_USER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The password associated with the username required for authentication with the SMTP server. + # JF_SMTP_PASSWORD: "" + ########################################################################### ## If your project uses a 'frogbot-config.yml' file, you should define ## ## the following variables inside the file, instead of here. ## @@ -165,6 +178,10 @@ pipelines: # Set the email of the commit author # JF_GIT_EMAIL_AUTHOR: "" + # [Mandatory if JF_SMTP_SERVER is set] + # List of email addresses to receive emails about secrets that has been detected in a pull request scan. + # The list should be seperated by commas. + # JF_EMAIL_RECEIVERS: "" execution: onExecute: - cd $res_frogbotGitRepo_resourcePath diff --git a/docs/templates/jfrog-pipelines/pipelines-maven.yml b/docs/templates/jfrog-pipelines/pipelines-maven.yml index 8cf9eb084..578bb7856 100644 --- a/docs/templates/jfrog-pipelines/pipelines-maven.yml +++ b/docs/templates/jfrog-pipelines/pipelines-maven.yml @@ -77,6 +77,19 @@ pipelines: # 3. Set the value of the 'JF_RELEASES_REPO' variable with the Repository Key you created. # JF_RELEASES_REPO: "" + # [Optional] + # Configure the SMTP server to enable Frogbot to send emails with detected secrets in pull request scans. + # SMTP server URL including should the relevant port: (Example: smtp.server.com:8080) + # JF_SMTP_SERVER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The username required for authenticating with the SMTP server. + # JF_SMTP_USER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The password associated with the username required for authentication with the SMTP server. + # JF_SMTP_PASSWORD: "" + ########################################################################### ## If your project uses a 'frogbot-config.yml' file, you should define ## ## the following variables inside the file, instead of here. ## @@ -153,6 +166,10 @@ pipelines: # Set the email of the commit author # JF_GIT_EMAIL_AUTHOR: "" + # [Mandatory if JF_SMTP_SERVER is set] + # List of email addresses to receive emails about secrets that has been detected in a pull request scan. + # The list should be seperated by commas. + # JF_EMAIL_RECEIVERS: "" execution: onExecute: - cd $res_frogbotGitRepo_resourcePath diff --git a/docs/templates/jfrog-pipelines/pipelines-npm.yml b/docs/templates/jfrog-pipelines/pipelines-npm.yml index 93abcca2e..85bf15258 100644 --- a/docs/templates/jfrog-pipelines/pipelines-npm.yml +++ b/docs/templates/jfrog-pipelines/pipelines-npm.yml @@ -77,6 +77,19 @@ pipelines: # 3. Set the value of the 'JF_RELEASES_REPO' variable with the Repository Key you created. # JF_RELEASES_REPO: "" + # [Optional] + # Configure the SMTP server to enable Frogbot to send emails with detected secrets in pull request scans. + # SMTP server URL including should the relevant port: (Example: smtp.server.com:8080) + # JF_SMTP_SERVER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The username required for authenticating with the SMTP server. + # JF_SMTP_USER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The password associated with the username required for authentication with the SMTP server. + # JF_SMTP_PASSWORD: "" + ########################################################################### ## If your project uses a 'frogbot-config.yml' file, you should define ## ## the following variables inside the file, instead of here. ## @@ -176,6 +189,10 @@ pipelines: # Set the email of the commit author # JF_GIT_EMAIL_AUTHOR: "" + # [Mandatory if JF_SMTP_SERVER is set] + # List of email addresses to receive emails about secrets that has been detected in a pull request scan. + # The list should be seperated by commas. + # JF_EMAIL_RECEIVERS: "" execution: onExecute: - cd $res_frogbotGitRepo_resourcePath diff --git a/docs/templates/jfrog-pipelines/pipelines-pip.yml b/docs/templates/jfrog-pipelines/pipelines-pip.yml index 44c6f8ae0..d864371c0 100644 --- a/docs/templates/jfrog-pipelines/pipelines-pip.yml +++ b/docs/templates/jfrog-pipelines/pipelines-pip.yml @@ -84,6 +84,19 @@ pipelines: # 3. Set the value of the 'JF_RELEASES_REPO' variable with the Repository Key you created. # JF_RELEASES_REPO: "" + # [Optional] + # Configure the SMTP server to enable Frogbot to send emails with detected secrets in pull request scans. + # SMTP server URL including should the relevant port: (Example: smtp.server.com:8080) + # JF_SMTP_SERVER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The username required for authenticating with the SMTP server. + # JF_SMTP_USER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The password associated with the username required for authentication with the SMTP server. + # JF_SMTP_PASSWORD: "" + ########################################################################### ## If your project uses a 'frogbot-config.yml' file, you should define ## ## the following variables inside the file, instead of here. ## @@ -164,6 +177,11 @@ pipelines: # Set the email of the commit author # JF_GIT_EMAIL_AUTHOR: "" + # [Mandatory if JF_SMTP_SERVER is set] + # List of email addresses to receive emails about secrets that has been detected in a pull request scan. + # The list should be seperated by commas. + # JF_EMAIL_RECEIVERS: "" + execution: onExecute: - cd $res_frogbotGitRepo_resourcePath diff --git a/docs/templates/jfrog-pipelines/pipelines-pipenv.yml b/docs/templates/jfrog-pipelines/pipelines-pipenv.yml index 9ad8b978d..ff81d7cd5 100644 --- a/docs/templates/jfrog-pipelines/pipelines-pipenv.yml +++ b/docs/templates/jfrog-pipelines/pipelines-pipenv.yml @@ -77,6 +77,19 @@ pipelines: # 3. Set the value of the 'JF_RELEASES_REPO' variable with the Repository Key you created. # JF_RELEASES_REPO: "" + # [Optional] + # Configure the SMTP server to enable Frogbot to send emails with detected secrets in pull request scans. + # SMTP server URL including should the relevant port: (Example: smtp.server.com:8080) + # JF_SMTP_SERVER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The username required for authenticating with the SMTP server. + # JF_SMTP_USER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The password associated with the username required for authentication with the SMTP server. + # JF_SMTP_PASSWORD: "" + ########################################################################### ## If your project uses a 'frogbot-config.yml' file, you should define ## ## the following variables inside the file, instead of here. ## @@ -157,6 +170,10 @@ pipelines: # Set the email of the commit author # JF_GIT_EMAIL_AUTHOR: "" + # [Mandatory if JF_SMTP_SERVER is set] + # List of email addresses to receive emails about secrets that has been detected in a pull request scan. + # The list should be seperated by commas. + # JF_EMAIL_RECEIVERS: "" execution: onExecute: - cd $res_frogbotGitRepo_resourcePath diff --git a/docs/templates/jfrog-pipelines/pipelines-poetry.yml b/docs/templates/jfrog-pipelines/pipelines-poetry.yml index 3ebfbec61..f87a47156 100644 --- a/docs/templates/jfrog-pipelines/pipelines-poetry.yml +++ b/docs/templates/jfrog-pipelines/pipelines-poetry.yml @@ -77,6 +77,19 @@ pipelines: # 3. Set the value of the 'JF_RELEASES_REPO' variable with the Repository Key you created. # JF_RELEASES_REPO: "" + # [Optional] + # Configure the SMTP server to enable Frogbot to send emails with detected secrets in pull request scans. + # SMTP server URL including should the relevant port: (Example: smtp.server.com:8080) + # JF_SMTP_SERVER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The username required for authenticating with the SMTP server. + # JF_SMTP_USER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The password associated with the username required for authentication with the SMTP server. + # JF_SMTP_PASSWORD: "" + ########################################################################### ## If your project uses a 'frogbot-config.yml' file, you should define ## ## the following variables inside the file, instead of here. ## @@ -157,6 +170,11 @@ pipelines: # Set the email of the commit author # JF_GIT_EMAIL_AUTHOR: "" + # [Mandatory if JF_SMTP_SERVER is set] + # List of email addresses to receive emails about secrets that has been detected in a pull request scan. + # The list should be seperated by commas. + # JF_EMAIL_RECEIVERS: "" + execution: onExecute: - cd $res_frogbotGitRepo_resourcePath diff --git a/docs/templates/jfrog-pipelines/pipelines-yarn2.yml b/docs/templates/jfrog-pipelines/pipelines-yarn2.yml index 0051a702a..3fe5f9036 100644 --- a/docs/templates/jfrog-pipelines/pipelines-yarn2.yml +++ b/docs/templates/jfrog-pipelines/pipelines-yarn2.yml @@ -84,6 +84,19 @@ pipelines: # 3. Set the value of the 'JF_RELEASES_REPO' variable with the Repository Key you created. # JF_RELEASES_REPO: "" + # [Optional] + # Configure the SMTP server to enable Frogbot to send emails with detected secrets in pull request scans. + # SMTP server URL including should the relevant port: (Example: smtp.server.com:8080) + # JF_SMTP_SERVER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The username required for authenticating with the SMTP server. + # JF_SMTP_USER: "" + + # [Mandatory if JF_SMTP_SERVER is set] + # The password associated with the username required for authentication with the SMTP server. + # JF_SMTP_PASSWORD: "" + ########################################################################### ## If your project uses a 'frogbot-config.yml' file, you should define ## ## the following variables inside the file, instead of here. ## @@ -160,6 +173,11 @@ pipelines: # Set the email of the commit author # JF_GIT_EMAIL_AUTHOR: "" + # [Mandatory if JF_SMTP_SERVER is set] + # List of email addresses to receive emails about secrets that has been detected in a pull request scan. + # The list should be seperated by commas. + # JF_EMAIL_RECEIVERS: "" + execution: onExecute: - cd $res_frogbotGitRepo_resourcePath diff --git a/go.mod b/go.mod index 704cc7b3b..12396789f 100644 --- a/go.mod +++ b/go.mod @@ -8,8 +8,9 @@ require ( github.com/jfrog/build-info-go v1.9.7 github.com/jfrog/froggit-go v1.13.1 github.com/jfrog/gofrog v1.3.0 - github.com/jfrog/jfrog-cli-core/v2 v2.40.0 + github.com/jfrog/jfrog-cli-core/v2 v2.40.1 github.com/jfrog/jfrog-client-go v1.31.4 + github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible github.com/mholt/archiver/v3 v3.5.1 github.com/stretchr/testify v1.8.4 github.com/urfave/cli/v2 v2.25.7 @@ -114,4 +115,4 @@ require ( gopkg.in/warnings.v0 v0.1.2 // indirect ) -replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230815113548-fdb5e0f22eb6 +//replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.15.3-0.20230815120022-ac47a4900afd diff --git a/go.sum b/go.sum index aabaf42d2..55f442b42 100644 --- a/go.sum +++ b/go.sum @@ -881,10 +881,12 @@ github.com/jfrog/froggit-go v1.13.1 h1:EcSGalen4Jmkn2MIzCA0RSgEBR2kKhXtVfsE5ZAE6 github.com/jfrog/froggit-go v1.13.1/go.mod h1:0jRAaZZusaFFnITosmx6CA60SKryuoaCasJyUrP/c1s= github.com/jfrog/gofrog v1.3.0 h1:o4zgsBZE4QyDbz2M7D4K6fXPTBJht+8lE87mS9bw7Gk= github.com/jfrog/gofrog v1.3.0/go.mod h1:IFMc+V/yf7rA5WZ74CSbXe+Lgf0iApEQLxRZVzKRUR0= -github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230815113548-fdb5e0f22eb6 h1:COPC1fI9HUoPdJmZxOIjXUJ79ng5Xno1opQ3uvE7rgQ= -github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20230815113548-fdb5e0f22eb6/go.mod h1:lcUAS1CD1ygKDyucrUNmpB1KdKdq+Ds6LbJjAKQB7T8= +github.com/jfrog/jfrog-cli-core/v2 v2.40.1 h1:OXQYI0RGlsFt5eWkLg8x60PZf5FImXNOrGfbMcir/SI= +github.com/jfrog/jfrog-cli-core/v2 v2.40.1/go.mod h1:lcUAS1CD1ygKDyucrUNmpB1KdKdq+Ds6LbJjAKQB7T8= github.com/jfrog/jfrog-client-go v1.31.4 h1:jUKwQ68yBBHQlwNzN6bY8sh1Ey8PbqOqh9mzkzp+yHc= github.com/jfrog/jfrog-client-go v1.31.4/go.mod h1:Yyz+Qjorop0CycJAjk67y6UbyLK5b7dQaPMcy1THIJw= +github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible h1:jdpOPRN1zP63Td1hDQbZW73xKmzDvZHzVdNYxhnTMDA= +github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible/go.mod h1:1c7szIrayyPPB/987hsnvNzLushdWf4o/79s3P08L8A= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= diff --git a/schema/frogbot-schema.json b/schema/frogbot-schema.json index 460d86f38..1630b8ce2 100644 --- a/schema/frogbot-schema.json +++ b/schema/frogbot-schema.json @@ -117,6 +117,21 @@ "description": "Handle vulnerabilities with fix versions only.", "title": "Handle vulnerabilities with fix versions only" }, + "emailReceivers": { + "type": [ + "array", + "null" + ], + "description": "List of email addresses to receive emails about secrets that has been detected in a pull request scan.", + "title": "List of email addresses to receive emails about secrets that has been detected in a pull request scan", + "items": { + "type": "string", + "title": "Email Address", + "examples": [ + "user@company.com" + ] + } + }, "projects": { "type": ["array", "null"], "title": "Projects in Git Repository",