Run Semgrep in Jenkins when using Bitbucket as the source code manager
To scan your code hosted by Bitbucket with Semgrep using a Jenkins project or pipeline, you must:
- Set up webhooks to connect Jenkins to Bitbucket.
- Configure the Jenkins project or pipeline to run Semgrep.
Set up webhooks to allow triggering events from Bitbucket to Jenkins
Webhooks are required to connect your Bitbucket source code manager (SCM) to Jenkins.
You must install the Bitbucket Push and Pull Request plugin on your Jenkins server. This method requires that your Jenkins instance be compatible with this plugin.
- Log in to Bitbucket, and go to your repository.
- In your Bitbucket repository, go to Repository Settings > Webhooks > Add webhook.
- Enter a Title for your webhook.
- Enter the URL for your Jenkins instance using the following pattern:
https://<YOUR_JENKINS_SERVER>/bitbucket-hook/. - Add the following Triggers:
- In the Repository list, select Push.
- In the Pull request list, select Created and Updated.
Configure Jenkins to run Semgrep
- Pipeline
- Freestyle
- Sign in to Jenkins.
- From the Jenkins Dashboard click on create a New Item.
- Enter a project name, select Pipeline option, and click OK.
- In the General > Triggers section, select Build with BitBucket Push and Pull Request Plugin.
- Create the Triggers:
- Click Add.
- Select one of the following: Bitbucket Cloud Pull Request, Bitbucket Server Pull Request, or Push.
- In Select an Action, select Created.
- Click Add again, and select the same trigger as before: Bitbucket Cloud Pull Request, Bitbucket Server Pull Request, or Push.
- In Select an Action, select Updated.
- Go to the Pipeline section. In Definition, select Pipeline script from SCM.
- In SCM, select Git.
- In Repositories > Repository URL, enter your Bitbucket repository URL.
- In Branch Specifier (blank for 'any'), enter the name of your main branch.
- In Script Path, enter
Jenkinsfile.
- Click Save.
Create and add the Jenkinsfile to your repository
Create the Jenkinsfile in your Bitbucket repository. The file must define the logic to start:
- Diff-aware scans if the scan is started in the context of a pull request
- Full scans if you push changes to the main branch.
The following code snippets are sample Jenkinsfile that defines both of these actions. Choose the file for your deployment based on whether you're using Bitbucket Cloud or Bitbucket Data Center.
- Bitbucket Cloud
- Bitbucket Data Center
pipeline {
agent any
environment {
SEMGREP_APP_TOKEN = credentials('SEMGREP_APP_TOKEN')
SEMGREP_BASELINE_REF = "origin/main"
}
stages {
stage('Semgrep-Scan') {
steps {
script {
if (env.BITBUCKET_PULL_REQUEST_ID) {
echo "Semgrep diff scan"
sh '''git checkout ${BITBUCKET_PULL_REQUEST_LATEST_COMMIT_FROM_SOURCE_BRANCH}'''
sh '''git fetch origin +ref/heads/*:refs/remotes/origin/*'''
sh '''docker run \
-e SEMGREP_APP_TOKEN=$SEMGREP_APP_TOKEN \
-e SEMGREP_PR_ID=${BITBUCKET_PULL_REQUEST_ID} \
-e SEMGREP_BASELINE_REF=$SEMGREP_BASELINE_REF \
-v "$(pwd):$(pwd)" --workdir $(pwd) \
semgrep/semgrep semgrep ci'''
}
else {
echo "Semgrep full scan"
sh '''docker run \
-e SEMGREP_APP_TOKEN=$SEMGREP_APP_TOKEN \
-v "$(pwd):$(pwd)" --workdir $(pwd) \
semgrep/semgrep semgrep ci'''
}
}
}
}
}
}
Note that:
- You must define
SEMGREP_APP_TOKENin Jenkins. You can create the required token in Semgrep AppSec Platform. - The variable
SEMGREP_BASELINE_REFin the code snippet must be set to the primary or default branch, which in the example isorigin/main.\
pipeline {
agent any
environment {
// The following variable is required for a Semgrep AppSec Platform-connected scan:
SEMGREP_APP_TOKEN = credentials('SEMGREP_APP_TOKEN')
BITBUCKET_TOKEN = credentials('FS_BITBUCKET_TOKEN')
// Uncomment the following line to scan changed
// files in PRs or MRs (diff-aware scanning):
// SEMGREP_BASELINE_REF = "${env.CHANGE_ID != null ? 'main' : ''}"
// Troubleshooting:
// Uncomment the following lines if Semgrep AppSec Platform > Findings Page does not create links
// to the code that generated a finding or if you are not receiving PR or MR comments.
// SEMGREP_JOB_URL = "${BUILD_URL}"
// SEMGREP_COMMIT = "${GIT_COMMIT}"
// SEMGREP_BRANCH = "${GIT_BRANCH}"
// SEMGREP_REPO_NAME = env.GIT_URL.replaceFirst(/^https:\/\/YOUR_BITBUCKET_DATA_CENTER_URL\/scm\/(.*).git$/, '$1')
// SEMGREP_REPO_URL = env.GIT_URL.replaceFirst(/^(https:\/\/.*?)\/scm\/(.*)\/(.*)\.git$/, '$1/projects/$2/repos/$3')
// SEMGREP_PR_ID = "${env.CHANGE_ID != null ? env.CHANGE_ID : ''}"
SEMGREP_APP_URL = "https://semgrep.dev"
}
stages {
stage('Semgrep-Scan') {
steps {
sh 'pip3 install semgrep'
sh 'semgrep ci'
}
}
}
}
To set up a Freestyle project to scan your Bitbucket projects with Semgrep:
- Sign in to Jenkins.
- Define
SEMGREP_APP_TOKENas a credential in Jenkins. You will add this credential to your project at a later step. - From the Jenkins Dashboard, click New Item.
- Type a project name, select Freestyle project, and click OK.
- Go to General > Source Code Management. Select Git. Then:
- Add your Bitbucket Repository URL
- Add the Credentials needed to check out your sources
- Add the Branches to build.
- In the Triggers section, select Build with Bitbucket Push and Pull Request Plugin. Then, create the Triggers:
- Click Add.
- Select one of the following: Bitbucket Cloud Pull Request or Bitbucket Server Pull Request.
- In Select an Action, select Created.
- Click Add again, and select the same trigger as before: Bitbucket Cloud Pull Request or Bitbucket Server Pull Request.
- In Select an Action, select Updated.
- Click Add > Push.
- Next, add your Semgrep token to the environment:
- In the Environment Section, select Use secret text(s) or file(s).
- Under Bindings, select Secret text.
- Set Variable to
SEMGREP_APP_TOKEN. - Under Credentials > Specific credentials, choose the defined credential for the token.
- Click Add to save your changes.
- In the Build Steps section, click Add build step > Execute shell. In Command, provide one of the following scripts to run Semgrep:
#!/bin/bash
BASELINE_REF="main"
BASELINE_REF_ORIGIN="origin/$BASELINE_REF"
REPO_URL=$GIT_URL
REPO_NAME=$(echo "$GIT_URL" | awk -F'/' '{print $(NF-1)"/"$(NF)}' | sed 's/.git$//')
## Merge or push to primary branch
if [ $BITBUCKET_SOURCE_BRANCH = $BASELINE_REF ]; then
docker run -e SEMGREP_APP_TOKEN=$SEMGREP_APP_TOKEN \
-e SEMGREP_REPO_URL=$REPO_URL \
-e SEMGREP_REPO_NAME=$REPO_NAME \
-v "$(pwd):$(pwd)" --workdir $(pwd) \
semgrep/semgrep semgrep ci
## pull request scans
elif [ $BITBUCKET_PULL_REQUEST_ID -ge 0 ]; then
git checkout $BITBUCKET_SOURCE_BRANCH && git pull
docker run -e SEMGREP_APP_TOKEN=$SEMGREP_APP_TOKEN \
-e SEMGREP_BASELINE_REF=$BASELINE_REF_ORIGIN \
-e SEMGREP_REPO_URL=$REPO_URL \
-e SEMGREP_REPO_NAME=$REPO_NAME \
-e SEMGREP_BRANCH=$BITBUCKET_SOURCE_BRANCH \
-e SEMGREP_PR_ID=$BITBUCKET_PULL_REQUEST_ID \
-v "$(pwd):/src" \
semgrep/semgrep semgrep ci
finote- The variable
SEMGREP_BASELINE_REFmust be set to the default branch, which ismainin the preceding example. - The configuration for a diff-aware scan must specify a merge base against which the pull request changes are compared. To do this:
- Set the pull request target branch as
SEMGREP_BASELINE_REF - Set
SEMGREP_BRANCHto the pull request source branch to ensure it's correctly identified. - Set
SEMGREP_PR_IDso that Semgrep can send comments to the relevant pull request.
- Set the pull request target branch as
- The variable
Test the implementation
To ensure that Semgrep scans correctly in your Jenkins pipeline or project:
- Commit a change to your repository, and create a pull request. This automatically runs a Semgrep diff-aware scan in Jenkins. Note that the job can fail if there are blocking findings as a result of the scan.
- Merge the pull request to commit the changes to
main. This triggers a full scan in Jenkins.
Not finding what you need in this doc? Ask questions in our Community Slack group, or see Support for other ways to get help.