CI/CD integration
Vulkro is built to run in CI. This page covers the common setups. For more depth, see Integrations.
How the exit code works
vulkro scan exits 1 if it finds any Critical or High issue, and 0
otherwise. That is the whole contract, so it drops into any CI runner:
vulkro scan . # fails the build on Critical/High
vulkro scan . --fail-on critical,high,medium # also fail on Medium
vulkro scan . --all-confidence # show everything; still gates on severity
--min-confidence controls which findings are shown. --fail-on controls
which severities fail the build.
A severity exit policy is Free: --fail-on and a plain scan --gate are
what the default preset uses, and no account is needed for them. The
diff-scoped family (vulkro gate, scan --gate-vs and the ratchet), the
pull-request comment and annotation formats, and vulkro ci are part of
Pro. See Pricing.
GitHub Actions
name: vulkro
on:
push:
branches: [main]
pull_request:
jobs:
scan:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write # required to upload SARIF
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # required to scan git history for secrets
- name: Install vulkro
run: curl -fsSL https://dist.vulkro.com/install.sh | bash
- name: Run scan (SARIF)
run: vulkro scan . --format sarif > vulkro.sarif
- name: Upload to GitHub Code Scanning
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: vulkro.sarif
- name: Block the PR on Critical/High
run: vulkro scan . --min-confidence high
There are two scan steps on purpose. The first always succeeds and produces SARIF, so the results always show up in GitHub Code Scanning. The second is the gate: it fails the build if there are unresolved Critical or High findings.
GitLab CI
vulkro:
stage: test
image: ubuntu:24.04
script:
- curl -fsSL https://dist.vulkro.com/install.sh | bash
- vulkro scan . --format junit > vulkro-junit.xml
- vulkro scan . --min-confidence high
artifacts:
when: always
reports:
junit: vulkro-junit.xml
paths:
- vulkro-junit.xml
expire_in: 30 days
The JUnit output shows up directly in GitLab's merge-request report, with every finding as a failed test and its file and line attached.
pre-commit (fast local check)
repos:
- repo: local
hooks:
- id: vulkro-fast
name: vulkro (fast, source only)
entry: vulkro scan . --min-confidence high --scope src
language: system
pass_filenames: false
stages: [pre-commit]
--scope src skips Dockerfiles, lockfiles, and templates to keep the hook fast.
Post results as a PR comment
The pull-request output (gh-pr, gh-pr-inline-comments,
github-annotations, gitlab-mr, bitbucket-pr, azure-pr) is part of
Pro: Pull-request output (pr-comments), findings as review comments
and CI annotations.
vulkro scan . --format gh-pr > comment.md
gh pr comment "$PR_NUMBER" --body-file comment.md
The comment summarizes the severity counts and links each Critical and High finding straight to the line of code.
Gate only on new problems
Part of Pro: Release gate (release-gate), fail a build on new
findings, with the exit-code contract and the baseline diff. To fail the
build only on issues that are new compared to main:
vulkro gate --base origin/main
vulkro gate scans both your branch and the base, then fails only on findings
that are new. Existing tech debt, re-ordering, and whitespace changes never fail
the build. See Baselines explained.
Useful environment variables
| Variable | Effect |
|---|---|
VULKRO_OFFLINE=1 | Skip the CVE download in air-gapped runners. |
VULKRO_GIT_BLAME=1 | Attach the code owner to each finding for reports. |
What's next
- GitHub Actions deep-dive -> - caching, monorepos, and matrices.
- Output formats -> - SBOMs, GDPR reports, and executive HTML.
- Compliance gating -> - block PRs on PCI DSS, SOC 2, or HIPAA control failures.