diff --git a/scanrepository/scanrepository.go b/scanrepository/scanrepository.go index 7e7bcc042..bdf9c8018 100644 --- a/scanrepository/scanrepository.go +++ b/scanrepository/scanrepository.go @@ -308,8 +308,9 @@ func (cfp *ScanRepositoryCmd) fixProjectVulnerabilities(repository *utils.Reposi } // Fix every vulnerability in a separate pull request and branch + projectPathFromRoot := projectWorkingDir for _, vulnerability := range vulnerabilities { - if e := cfp.fixSinglePackageAndCreatePR(repository, vulnerability); e != nil { + if e := cfp.fixSinglePackageAndCreatePR(repository, projectPathFromRoot, vulnerability); e != nil { err = errors.Join(err, cfp.handleUpdatePackageErrors(e)) } @@ -386,10 +387,11 @@ func (cfp *ScanRepositoryCmd) handleUpdatePackageErrors(err error) error { // Creates a branch for the fixed package and open pull request against the target branch. // In case a branch already exists on remote, we skip it. -func (cfp *ScanRepositoryCmd) fixSinglePackageAndCreatePR(repository *utils.Repository, vulnDetails *utils.VulnerabilityDetails) (err error) { +// projectPathFromRoot is the relative path of the project from the repository root (used for branch name uniqueness). +func (cfp *ScanRepositoryCmd) fixSinglePackageAndCreatePR(repository *utils.Repository, projectPathFromRoot string, vulnDetails *utils.VulnerabilityDetails) (err error) { fixVersion := vulnDetails.SuggestedFixedVersion log.Debug("Attempting to fix", fmt.Sprintf("%s:%s", vulnDetails.ImpactedDependencyName, vulnDetails.ImpactedDependencyVersion), "with", fixVersion) - fixBranchName, err := cfp.gitManager.GenerateFixBranchName(cfp.scanDetails.BaseBranch(), vulnDetails.ImpactedDependencyName, fixVersion) + fixBranchName, err := cfp.gitManager.GenerateFixBranchName(cfp.scanDetails.BaseBranch(), vulnDetails.ImpactedDependencyName, fixVersion, projectPathFromRoot) if err != nil { return } diff --git a/scanrepository/scanrepository_test.go b/scanrepository/scanrepository_test.go index 070d5765a..11840a109 100644 --- a/scanrepository/scanrepository_test.go +++ b/scanrepository/scanrepository_test.go @@ -15,8 +15,6 @@ import ( "github.com/CycloneDX/cyclonedx-go" "github.com/google/go-github/v45/github" biutils "github.com/jfrog/build-info-go/utils" - "github.com/jfrog/frogbot/v2/utils" - "github.com/jfrog/frogbot/v2/utils/outputwriter" "github.com/jfrog/froggit-go/vcsclient" "github.com/jfrog/froggit-go/vcsutils" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" @@ -31,6 +29,9 @@ import ( "github.com/jfrog/jfrog-client-go/xray/services" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/jfrog/frogbot/v2/utils" + "github.com/jfrog/frogbot/v2/utils/outputwriter" ) const rootTestDir = "scanrepository" @@ -392,16 +393,20 @@ func TestGenerateFixBranchName(t *testing.T) { baseBranch string impactedPackage string fixVersion string + projectPath string expectedName string }{ - {"dev", "gopkg.in/yaml.v3", "3.0.0", "frogbot-gopkg.in/yaml.v3-d61bde82dc594e5ccc5a042fe224bf7c"}, - {"master", "gopkg.in/yaml.v3", "3.0.0", "frogbot-gopkg.in/yaml.v3-41405528994061bd108e3bbd4c039a03"}, - {"dev", "replace:colons:colons", "3.0.0", "frogbot-replace_colons_colons-89e555131b4a70a32fe9d9c44d6ff0fc"}, + {"dev", "gopkg.in/yaml.v3", "3.0.0", "", "frogbot-gopkg.in/yaml.v3-d61bde82dc594e5ccc5a042fe224bf7c"}, + {"master", "gopkg.in/yaml.v3", "3.0.0", "", "frogbot-gopkg.in/yaml.v3-41405528994061bd108e3bbd4c039a03"}, + {"dev", "replace:colons:colons", "3.0.0", "", "frogbot-replace_colons_colons-89e555131b4a70a32fe9d9c44d6ff0fc"}, + {"main", "requests", "2.25.3", "", "frogbot-requests-ae6fef399c0fdd96441b0215f28147d2"}, + {"main", "requests", "2.25.3", "subfolder", "frogbot-requests-28662794aa63a6250dd9a80f7618f841"}, + {"main", "requests", "2.25.3", "other/project", "frogbot-requests-61eeddf6eda4b867a2b75fa5630875e8"}, } gitManager := utils.GitManager{} for _, test := range tests { t.Run(test.expectedName, func(t *testing.T) { - branchName, err := gitManager.GenerateFixBranchName(test.baseBranch, test.impactedPackage, test.fixVersion) + branchName, err := gitManager.GenerateFixBranchName(test.baseBranch, test.impactedPackage, test.fixVersion, test.projectPath) assert.NoError(t, err) assert.Equal(t, test.expectedName, branchName) }) diff --git a/utils/git.go b/utils/git.go index 22bd26f86..5e1375a1a 100644 --- a/utils/git.go +++ b/utils/git.go @@ -4,7 +4,6 @@ import ( "errors" "fmt" "net/http" - "regexp" "strings" "time" @@ -486,8 +485,12 @@ func formatStringWithPlaceHolders(str, impactedPackage, fixVersion, hash, baseBr return str } -func (gm *GitManager) GenerateFixBranchName(branch string, impactedPackage string, fixVersion string) (string, error) { - hash, err := Md5Hash("frogbot", branch, impactedPackage, fixVersion) +func (gm *GitManager) GenerateFixBranchName(branch string, impactedPackage string, fixVersion string, projectPath string) (string, error) { + hashInputs := []string{"frogbot", branch, impactedPackage, fixVersion} + if projectPath != "" { + hashInputs = append(hashInputs, projectPath) + } + hash, err := Md5Hash(hashInputs...) if err != nil { return "", err } diff --git a/utils/git_test.go b/utils/git_test.go index b1208a75e..d6c44da0b 100644 --- a/utils/git_test.go +++ b/utils/git_test.go @@ -96,7 +96,7 @@ func TestGitManager_GenerateFixBranchName(t *testing.T) { } for _, test := range testCases { t.Run(test.expected, func(t *testing.T) { - commitMessage, err := test.gitManager.GenerateFixBranchName("md5Branch", test.impactedPackage, test.fixVersion.SuggestedFixedVersion) + commitMessage, err := test.gitManager.GenerateFixBranchName("md5Branch", test.impactedPackage, test.fixVersion.SuggestedFixedVersion, "") assert.NoError(t, err) assert.Equal(t, test.expected, commitMessage) }) diff --git a/utils/utils.go b/utils/utils.go index fac886853..8d5b39cb5 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -561,6 +561,7 @@ func isUrlAccessible(url string) bool { return false } log.Debug(fmt.Sprintf("Sending HTTP %s request to: '%s'", req.Method, req.URL)) + // #nosec G704 -- URL is from Frogbot config (FrogbotRepoUrl), not user input resp, err := client.GetClient().Do(req) if errorutils.CheckError(err) != nil { log.Debug(fmt.Sprintf("Can't check access to '%s', error while sending request:\n%s", url, err.Error()))