Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,89 @@ jobs:
JF_ACCESS_TOKEN: ${{ secrets.PLATFORM_ADMIN_TOKEN }}
FROGBOT_V3_TESTS_GITLAB_TOKEN: ${{ secrets.FROGBOT_V3_TESTS_GITLAB_TOKEN }}

bitbucket-cloud-integration:
name: Bitbucket Cloud Integration Tests
needs: Pretest
runs-on: ${{ matrix.os }}-latest
strategy:
fail-fast: false
max-parallel: 1
matrix:
os: [ ubuntu, windows, macos ]
concurrency:
group: bitbucket-cloud-integration-fixture
cancel-in-progress: false
env:
JFROG_CLI_LOG_LEVEL: "DEBUG"
steps:
- uses: actions/checkout@v7
with:
ref: ${{ github.event.pull_request.head.sha }}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
allow-unsafe-pr-checkout: true
persist-credentials: false

- uses: jfrog/boost@v0
with:
accept_terms: yes

- name: Setup Go
uses: actions/setup-go@v5
with:
go-version-file: 'go.mod'
cache: false
- name: Go Cache Build & Tests
uses: actions/cache@v4
with:
path: |
~/.cache/go-build
~\AppData\Local\go-build
~/Library/Caches/go-build
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}-${{ hashFiles('**/*.go') }}
restore-keys: |
${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}-
${{ runner.os }}-go-

- name: Run Tests
run: go test -tags integration -run 'TestBitbucketCloud_' bitbucket_cloud_test.go integrationutils.go commands.go -v -race -timeout 30m -cover
env:
JF_URL: ${{ secrets.PLATFORM_URL }}
JF_ACCESS_TOKEN: ${{ secrets.PLATFORM_ADMIN_TOKEN }}
FROGBOT_V3_TESTS_BITBUCKET_CLOUD_TOKEN: ${{ secrets.FROGBOT_V3_TESTS_BITBUCKET_CLOUD_TOKEN }}
Comment on lines +435 to +482

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔌 Services Vulnerability

Severity Finding
high
High
Has unprotected jobs (fork)
Full description

Vulnerability Details

Rule ID: REQ.SW.GITHUB-ACTIONS.CODE-EXEC

A GitHub workflow that runs on pull_request_target and checks out the pull request code may be vulnerable to GitHub Actions code injection. An attacker can open a pull request from a forked repository and include malicious code that executes within the workflow's context. Depending on the workflow's permissions and environment, the attacker's code may perform unauthorized or harmful actions.

An attacker may exploit the workflow to access sensitive data available in the workflow's environment, such as API keys or other secrets. Additionally, if the workflow has write permissions to the repository, the attacker may be able to modify the project by pushing malicious code.

If possible, avoid using workflows triggered by pull_request_target. If this trigger is required, do not check out the pull request's code. If checking out the code cannot be avoided, ensure that the workflow does not execute commands that run actions based on the pull request's contents (for example, npm install or cmake). Additionally, validate that the pull request was created by a trusted actor before running the workflow.



Comment on lines +435 to +482

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔌 Services Vulnerability

Severity Finding
high
High
Has unprotected jobs
Full description

Vulnerability Details

Rule ID: REQ.SW.GITHUB-ACTIONS.CODE-EXEC

A GitHub workflow that runs on pull_request_target and checks out the pull request code may be vulnerable to GitHub Actions code injection. An attacker can open a pull request from a forked repository and include malicious code that executes within the workflow's context. Depending on the workflow's permissions and environment, the attacker's code may perform unauthorized or harmful actions.

An attacker may exploit the workflow to access sensitive data available in the workflow's environment, such as API keys or other secrets. Additionally, if the workflow has write permissions to the repository, the attacker may be able to modify the project by pushing malicious code.

If possible, avoid using workflows triggered by pull_request_target. If this trigger is required, do not check out the pull request's code. If checking out the code cannot be avoided, ensure that the workflow does not execute commands that run actions based on the pull request's contents (for example, npm install or cmake). Additionally, validate that the pull request was created by a trusted actor before running the workflow.




bitbucket-cloud-integration-cleanup:
name: Cleanup Bitbucket Cloud Integration Test Artifacts
needs: [ Pretest, bitbucket-cloud-integration ]
if: ${{ always() && !cancelled() && needs.Pretest.result != 'skipped' && needs.bitbucket-cloud-integration.result != 'skipped' }}
runs-on: ubuntu-latest
concurrency:
group: bitbucket-cloud-integration-fixture
cancel-in-progress: false
env:
JFROG_CLI_LOG_LEVEL: "DEBUG"
steps:
- uses: actions/checkout@v7
with:
ref: ${{ github.event.pull_request.head.sha }}
allow-unsafe-pr-checkout: true
persist-credentials: false

- uses: jfrog/boost@v0
with:
accept_terms: yes

- name: Setup Go
uses: actions/setup-go@v5
with:
go-version-file: 'go.mod'
cache: false

- name: Run Cleanup
run: go test -tags integration -run TestHelper_CleanupIntegrationTestsArtifactsBitbucketCloud bitbucket_cloud_test.go integrationutils.go commands.go -v
env:
JF_URL: ${{ secrets.PLATFORM_URL }}
JF_ACCESS_TOKEN: ${{ secrets.PLATFORM_ADMIN_TOKEN }}
FROGBOT_V3_TESTS_BITBUCKET_CLOUD_TOKEN: ${{ secrets.FROGBOT_V3_TESTS_BITBUCKET_CLOUD_TOKEN }}
Comment on lines +484 to +516

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔌 Services Vulnerability

Severity Finding
high
High
Has unprotected jobs (fork)
Full description

Vulnerability Details

Rule ID: REQ.SW.GITHUB-ACTIONS.CODE-EXEC

A GitHub workflow that runs on pull_request_target and checks out the pull request code may be vulnerable to GitHub Actions code injection. An attacker can open a pull request from a forked repository and include malicious code that executes within the workflow's context. Depending on the workflow's permissions and environment, the attacker's code may perform unauthorized or harmful actions.

An attacker may exploit the workflow to access sensitive data available in the workflow's environment, such as API keys or other secrets. Additionally, if the workflow has write permissions to the repository, the attacker may be able to modify the project by pushing malicious code.

If possible, avoid using workflows triggered by pull_request_target. If this trigger is required, do not check out the pull request's code. If checking out the code cannot be avoided, ensure that the workflow does not execute commands that run actions based on the pull request's contents (for example, npm install or cmake). Additionally, validate that the pull request was created by a trusted actor before running the workflow.



Comment on lines +484 to +516

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔌 Services Vulnerability

Severity Finding
high
High
Has unprotected jobs
Full description

Vulnerability Details

Rule ID: REQ.SW.GITHUB-ACTIONS.CODE-EXEC

A GitHub workflow that runs on pull_request_target and checks out the pull request code may be vulnerable to GitHub Actions code injection. An attacker can open a pull request from a forked repository and include malicious code that executes within the workflow's context. Depending on the workflow's permissions and environment, the attacker's code may perform unauthorized or harmful actions.

An attacker may exploit the workflow to access sensitive data available in the workflow's environment, such as API keys or other secrets. Additionally, if the workflow has write permissions to the repository, the attacker may be able to modify the project by pushing malicious code.

If possible, avoid using workflows triggered by pull_request_target. If this trigger is required, do not check out the pull request's code. If checking out the code cannot be avoided, ensure that the workflow does not execute commands that run actions based on the pull request's contents (for example, npm install or cmake). Additionally, validate that the pull request was created by a trusted actor before running the workflow.




bitbucket-server-integration:
name: Bitbucket Server Integration Tests
needs: Pretest
Expand Down
56 changes: 56 additions & 0 deletions bitbucket_cloud_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//go:build integration

package main

import (
"github.com/jfrog/frogbot/v3/utils"
"github.com/jfrog/froggit-go/vcsclient"
"github.com/jfrog/froggit-go/vcsutils"
"github.com/stretchr/testify/assert"
"testing"
)

const (
//#nosec G101 -- False positive - no hardcoded credentials.
bitbucketCloudIntegrationTokenEnv = "FROGBOT_V3_TESTS_BITBUCKET_CLOUD_TOKEN"
bitbucketCloudGitCloneUrl = "https://bitbucket.org/frogbot-e2e-test/frogbot-test.git"
bitbucketCloudRepoOwner = "frogbot-e2e-test"
// Matches utils.toBasicAuth's own default for git operations. Bitbucket Cloud's REST API rejects
// this username though, hence GitPushUsername being kept separate from the (empty) REST username.
bitbucketCloudGitPushUsername = "x-token-auth"
)

func buildBitbucketCloudClient(t *testing.T, bitbucketCloudToken string) vcsclient.VcsClient {
bbClient, err := vcsclient.NewClientBuilder(vcsutils.BitbucketCloud).Token(bitbucketCloudToken).Build()
assert.NoError(t, err)
return bbClient
}

func buildBitbucketCloudIntegrationTestDetails(t *testing.T) *IntegrationTestDetails {
integrationRepoToken := getIntegrationToken(t, bitbucketCloudIntegrationTokenEnv)
testDetails := NewIntegrationTestDetails(integrationRepoToken, string(utils.BitbucketCloud), bitbucketCloudGitCloneUrl, bitbucketCloudRepoOwner)
testDetails.GitUsername = ""
testDetails.GitPushUsername = bitbucketCloudGitPushUsername
Comment thread
eranturgeman marked this conversation as resolved.
return testDetails
}

func bitbucketCloudTestsInit(t *testing.T) (vcsclient.VcsClient, *IntegrationTestDetails) {
testDetails := buildBitbucketCloudIntegrationTestDetails(t)
bbClient := buildBitbucketCloudClient(t, testDetails.GitToken)
return bbClient, testDetails
}

func TestBitbucketCloud_ScanPullRequestIntegration(t *testing.T) {
bbClient, testDetails := bitbucketCloudTestsInit(t)
runScanPullRequestCmd(t, bbClient, testDetails)
}

func TestBitbucketCloud_ScanRepositoryIntegration(t *testing.T) {
bbClient, testDetails := bitbucketCloudTestsInit(t)
runScanRepositoryCmd(t, bbClient, testDetails)
}

func TestHelper_CleanupIntegrationTestsArtifactsBitbucketCloud(t *testing.T) {
bbClient, testDetails := bitbucketCloudTestsInit(t)
cleanupIntegrationArtifacts(t, bbClient, testDetails)
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -140,4 +140,4 @@ require (

// replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go master

// replace github.com/jfrog/froggit-go => github.com/jfrog/froggit-go master
replace github.com/jfrog/froggit-go => github.com/jfrog/froggit-go v1.23.2-0.20260909160929-7d982ce8ac90
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,8 @@ github.com/jfrog/archiver/v3 v3.6.5 h1:AiNXJoe8jYDOtyykfVuwh26aM4rk/ei+YzBpfBukd
github.com/jfrog/archiver/v3 v3.6.5/go.mod h1:5V9l+Fte30Y4qe9dUOAd3yNTf8lmtVNuhKNrvI8PMhg=
github.com/jfrog/build-info-go v1.13.1-0.20260902120316-b325d342b210 h1:u1Ijj6fOX9hCzz27L3IpqFqdSsjOlg6Td7URtmNFVR8=
github.com/jfrog/build-info-go v1.13.1-0.20260902120316-b325d342b210/go.mod h1:CYRUCvLKfyARjoJXLWAxce1qNUxTEtbRKAARkV42vpE=
github.com/jfrog/froggit-go v1.23.1 h1:4wmaHeuptxVINbovMaeITzVhi3+VQoc/FFIjF4axzu0=
github.com/jfrog/froggit-go v1.23.1/go.mod h1:wRDryqyp3oe+eHgME2mpnEQmO8XBECIPagFwj0nHmdI=
github.com/jfrog/froggit-go v1.23.2-0.20260909160929-7d982ce8ac90 h1:PKe1Qo+/leup348YO8UXCK5wZmfgW8mSy2vE+XM4Dzw=
github.com/jfrog/froggit-go v1.23.2-0.20260909160929-7d982ce8ac90/go.mod h1:wRDryqyp3oe+eHgME2mpnEQmO8XBECIPagFwj0nHmdI=
github.com/jfrog/gofrog v1.7.7 h1:I2MSi+ytPqfprhOC+MLDk5fVvuRzVjTqNkzrp9RtEvY=
github.com/jfrog/gofrog v1.7.7/go.mod h1:b/eFC21upqkt+fNwWXnAEkhjeAgP9b2gu55kT8ovAJU=
github.com/jfrog/jfrog-apps-config v1.0.1 h1:mtv6k7g8A8BVhlHGlSveapqf4mJfonwvXYLipdsOFMY=
Expand Down
25 changes: 22 additions & 3 deletions integrationutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,19 @@ type IntegrationTestDetails struct {
GitProvider string
GitProject string
GitUsername string
GitPushUsername string
ApiEndpoint string
PullRequestID string
CustomBranchName string
}

func (d *IntegrationTestDetails) gitPushUsername() string {
if d.GitPushUsername != "" {
return d.GitPushUsername
}
return d.GitUsername
}

func NewIntegrationTestDetails(token, gitProvider, gitCloneUrl, repoOwner string) *IntegrationTestDetails {
return &IntegrationTestDetails{
GitProject: repoName,
Expand All @@ -63,7 +71,7 @@ func NewIntegrationTestDetails(token, gitProvider, gitCloneUrl, repoOwner string

func buildGitManager(t *testing.T, testDetails *IntegrationTestDetails) *utils.GitManager {
gitManager, err := utils.NewGitManager().
SetAuth(testDetails.GitUsername, testDetails.GitToken).
SetAuth(testDetails.gitPushUsername(), testDetails.GitToken).
SetRemoteGitUrl(testDetails.GitCloneURL)
assert.NoError(t, err)
return gitManager
Expand Down Expand Up @@ -200,7 +208,7 @@ func runScanRepositoryCmd(t *testing.T, client vcsclient.VcsClient, testDetails
cloneOptions := &git.CloneOptions{
URL: testDetails.GitCloneURL,
Auth: &githttp.BasicAuth{
Username: testDetails.GitUsername,
Username: testDetails.gitPushUsername(),
Password: testDetails.GitToken,
},
RemoteName: "origin",
Expand Down Expand Up @@ -270,7 +278,7 @@ func cleanupIntegrationArtifacts(t *testing.T, client vcsclient.VcsClient, testD
cloneOptions := &git.CloneOptions{
URL: testDetails.GitCloneURL,
Auth: &githttp.BasicAuth{
Username: testDetails.GitUsername,
Username: testDetails.gitPushUsername(),
Password: testDetails.GitToken,
},
RemoteName: "origin",
Expand Down Expand Up @@ -316,6 +324,8 @@ func validateResults(t *testing.T, ctx context.Context, client vcsclient.VcsClie
validateAzureComments(t, comments)
case *vcsclient.BitbucketServerClient:
validateBitbucketServerComments(t, comments)
case *vcsclient.BitbucketCloudClient:
validateBitbucketCloudComments(t, comments)
case *vcsclient.GitLabClient:
validateGitLabComments(t, comments)
}
Expand Down Expand Up @@ -349,6 +359,15 @@ func validateBitbucketServerComments(t *testing.T, comments []vcsclient.CommentI
assertBannerExists(t, comments, outputwriter.GetSimplifiedTitle(outputwriter.VulnerabilitiesPrBannerSource))
}

func validateBitbucketCloudComments(t *testing.T, comments []vcsclient.CommentInfo) {
assert.True(t, containsCommentMentioning(comments, outputwriter.GetSimplifiedTitle(outputwriter.VulnerabilitiesPrBannerSource)),
"expected a PR comment containing the Frogbot banner")
assert.True(t, containsCommentMentioning(comments, scanPrTestAddedVulnDependency),
"expected a PR comment mentioning the vulnerable dependency "+scanPrTestAddedVulnDependency)
assert.True(t, containsCommentMentioning(comments, cveCommentPrefix),
"expected a PR comment with CVE findings")
}

func validateGitLabComments(t *testing.T, comments []vcsclient.CommentInfo) {
assert.True(t, containsCommentMentioning(comments, string(outputwriter.VulnerabilitiesMrBannerSource)),
"expected a MR comment containing the Frogbot banner")
Expand Down
Loading