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
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:
- 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.
- The second run is the gate.
--min-confidence highkeeps 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"