@@ -207,8 +207,7 @@ func auditTargetBranch(repoConfig *utils.Repository, scanDetails *utils.ScanDeta
207207 // Download target branch (if needed)
208208 cleanupTarget := func () error { return nil }
209209 if ! repoConfig .IncludeAllVulnerabilities {
210- targetBranchInfo := repoConfig .PullRequestDetails .Target
211- if targetBranchWd , cleanupTarget , err = utils .DownloadRepoToTempDir (scanDetails .Client (), targetBranchInfo .Owner , targetBranchInfo .Repository , targetBranchInfo .Name ); err != nil {
210+ if targetBranchWd , cleanupTarget , err = prepareTargetForScan (repoConfig .PullRequestDetails , scanDetails ); err != nil {
212211 return
213212 }
214213 }
@@ -230,6 +229,64 @@ func auditTargetBranch(repoConfig *utils.Repository, scanDetails *utils.ScanDeta
230229 return
231230}
232231
232+ func prepareTargetForScan (pullRequestDetails vcsclient.PullRequestInfo , scanDetails * utils.ScanDetails ) (targetBranchWd string , cleanupTarget func () error , err error ) {
233+ target := pullRequestDetails .Target
234+ // Download target branch
235+ if targetBranchWd , cleanupTarget , err = utils .DownloadRepoToTempDir (scanDetails .Client (), target .Owner , target .Repository , target .Name ); err != nil {
236+ return
237+ }
238+ if ! scanDetails .Git .UseMostCommonAncestorAsTarget {
239+ return
240+ }
241+ log .Debug ("Using most common ancestor commit as target branch commit" )
242+ // Get common parent commit between source and target and use it (checkout) to the target branch commit
243+ if e := tryCheckoutToMostCommonAncestor (scanDetails , pullRequestDetails .Source .Name , target .Name , targetBranchWd ); e != nil {
244+ log .Warn (fmt .Sprintf ("Failed to get best common ancestor commit between source branch: %s and target branch: %s, defaulting to target branch commit. Error: %s" , pullRequestDetails .Source .Name , target .Name , e .Error ()))
245+ }
246+ return
247+ }
248+
249+ func tryCheckoutToMostCommonAncestor (scanDetails * utils.ScanDetails , baseBranch , headBranch , targetBranchWd string ) (err error ) {
250+ repositoryInfo , err := scanDetails .Client ().GetRepositoryInfo (context .Background (), scanDetails .RepoOwner , scanDetails .RepoName )
251+ if err != nil {
252+ return
253+ }
254+ scanDetails .Git .RepositoryCloneUrl = repositoryInfo .CloneInfo .HTTP
255+ bestAncestorHash , err := getMostCommonAncestorCommitHash (scanDetails , baseBranch , headBranch )
256+ if err != nil {
257+ return
258+ }
259+ return checkoutToCommitAtTempWorkingDir (scanDetails , bestAncestorHash , targetBranchWd )
260+ }
261+
262+ func getMostCommonAncestorCommitHash (scanDetails * utils.ScanDetails , baseBranch , headBranch string ) (hash string , err error ) {
263+ gitManager , err := utils .NewGitManager ().SetAuth (scanDetails .Username , scanDetails .Token ).SetRemoteGitUrl (scanDetails .Git .RepositoryCloneUrl )
264+ if err != nil {
265+ return
266+ }
267+ return gitManager .GetMostCommonAncestorHash (baseBranch , headBranch )
268+ }
269+
270+ func checkoutToCommitAtTempWorkingDir (scanDetails * utils.ScanDetails , commitHash , wd string ) (err error ) {
271+ // Change working directory to the temp target branch directory
272+ cwd , err := os .Getwd ()
273+ if err != nil {
274+ return
275+ }
276+ if err = os .Chdir (wd ); err != nil {
277+ return
278+ }
279+ defer func () {
280+ err = errors .Join (err , os .Chdir (cwd ))
281+ }()
282+ // Load .git info in directory and Checkout to the commit hash
283+ gitManager , err := utils .NewGitManager ().SetAuth (scanDetails .Username , scanDetails .Token ).SetRemoteGitUrl (scanDetails .Git .RepositoryCloneUrl )
284+ if err != nil {
285+ return
286+ }
287+ return gitManager .CheckoutToHash (commitHash , wd )
288+ }
289+
233290func getAllIssues (cmdResults * results.SecurityCommandResults , allowedLicenses []string , hasViolationContext bool ) (* utils.IssuesCollection , error ) {
234291 log .Info ("Frogbot is configured to show all vulnerabilities" )
235292 simpleJsonResults , err := conversion .NewCommandResultsConvertor (conversion.ResultConvertParams {
0 commit comments