Skip to main content

Bitbucket Pipelines

Drop vulkro into a Bitbucket pipeline as a build step that publishes JUnit so findings show up in the pipeline's Tests tab, and gates the default branch on Critical/High results.

Minimal pipeline

bitbucket-pipelines.yml
image: ubuntu:24.04

pipelines:
default:
- step:
name: vulkro scan
script:
- curl -fsSL https://dist.vulkro.com/install.sh | bash
- export PATH="$HOME/.local/bin:$PATH"
- vulkro scan . --format junit > vulkro-junit.xml
- vulkro scan . --min-confidence high
artifacts:
- vulkro-junit.xml
after-script:
# Bitbucket auto-discovers JUnit XML under `**/test-results/`,
# but also accepts any uploaded artefact named `*junit*.xml`.
- echo "JUnit artefact uploaded; check the Tests tab on this run."

The two vulkro scan calls are intentional:

  1. The first run produces JUnit (always exits 0 because we don't gate on its exit code) - Bitbucket picks the artefact up so the Tests tab on the pipeline run lights up.
  2. The second run is the gate. --min-confidence high keeps the CI signal-to-noise high.

Caching the binary

Bitbucket caches are keyed off of the directory path:

definitions:
caches:
vulkro: $HOME/.local/bin

pipelines:
default:
- step:
name: vulkro scan
caches:
- vulkro
script:
- test -x "$HOME/.local/bin/vulkro" \
|| curl -fsSL https://dist.vulkro.com/install.sh \
| VULKRO_BIN_DIR="$HOME/.local/bin" bash
- export PATH="$HOME/.local/bin:$PATH"
- vulkro scan . --format junit > vulkro-junit.xml
- vulkro scan . --min-confidence high

A warm-cache install takes <1 s; the cold install plus first-run CVE bundle fetch is ~10 s.

PR-only pipeline (gate against the base branch)

Bitbucket runs pull-requests pipelines on every PR push. Use this shape to scan only against the merge base:

pipelines:
pull-requests:
'**':
- step:
name: vulkro PR scan
script:
- curl -fsSL https://dist.vulkro.com/install.sh | bash
- export PATH="$HOME/.local/bin:$PATH"
# `--gate-vs` reports findings on lines changed against the
# PR target. Full-repo findings are still in the JUnit artefact.
- vulkro scan . --format junit > vulkro-junit.xml
- vulkro scan . --gate-vs "origin/$BITBUCKET_PR_DESTINATION_BRANCH"
artifacts:
- vulkro-junit.xml

BITBUCKET_PR_DESTINATION_BRANCH is a built-in variable populated only in pull-requests pipelines, so this step won't run on plain pushes.

Ratchet mode (upcoming)

A --ratchet flag is on the way: it locks the baseline at the PR's merge base and fails the build only when new findings appear on changed lines. The pipeline above becomes:

# Upcoming flag - not yet released.
- vulkro scan . --ratchet --base "origin/$BITBUCKET_PR_DESTINATION_BRANCH"

Until it lands, --gate-vs is the closest equivalent shipping today and works on every released version.

SARIF artefact

Bitbucket has no native SARIF renderer, but you can still emit the file as a downloadable artefact for external dashboards (Defect Dojo, GitHub Code Scanning import, Snyk Trail-of-Bits, etc.):

- vulkro scan . --format sarif > vulkro.sarif
artifacts:
- vulkro.sarif

On PR comments

Bitbucket does not expose a first-class PR-comment surface to free pipeline jobs the way GitHub Actions does - there's no gh pr comment equivalent in the runner image, and the REST API requires either an OAuth consumer or an App password configured per workspace. We don't ship a wrapper for this because the auth shape varies by team setup and is easy to misconfigure.

If you have a workspace App password handy and want a comment, the shape is:

vulkro scan . --format gh-pr > comment.md
curl -X POST \
-u "$BB_USER:$BB_APP_PASSWORD" \
-H 'Content-Type: application/json' \
-d "{\"content\":{\"raw\":$(jq -Rs . < comment.md)}}" \
"https://api.bitbucket.org/2.0/repositories/$BITBUCKET_REPO_FULL_NAME/pullrequests/$BITBUCKET_PR_ID/comments"

For most teams, the JUnit + artefact pattern above is enough.

Air-gapped runners

For self-hosted runners that can't reach the public install script:

script:
- curl -fsSL https://artifacts.internal/vulkro/install.sh | bash
- export PATH="$HOME/.local/bin:$PATH"
variables:
VULKRO_OFFLINE: "1"
VULKRO_CDN_BASE_URL: "https://artifacts.internal/vulkro-cve"