GitHub Actions
A drop-in workflow that scans every push and PR, uploads SARIF to Code Scanning, and blocks merges on new Critical/High findings.
Minimal workflow
.github/workflows/vulkro.yml
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
- 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 PR on new Critical/High
run: vulkro scan . --min-confidence high
Caching the binary + CVE bundle
Speed up subsequent runs by caching ~/.local/bin/vulkro and
~/.vulkro/data/:
- name: Cache vulkro
uses: actions/cache@v4
id: cache
with:
path: |
~/.local/bin/vulkro
~/.vulkro/data
key: vulkro-${{ runner.os }}-v0.3.0
- name: Install vulkro
if: steps.cache.outputs.cache-hit != 'true'
run: |
curl -fsSL https://dist.vulkro.com/install.sh \
| VULKRO_BIN_DIR="$HOME/.local/bin" bash
A cached install takes <1 s. Without cache, the install + first-run CVE bundle fetch is ~10 s.
PR-scoped scans (only-new-findings gate)
- name: Scan only changed lines
run: vulkro scan . --gate-vs origin/${{ github.base_ref }}
if: github.event_name == 'pull_request'
Reports the diff-scoped findings as the gate; full repo findings are still emitted in JSON for completeness.
PR-comment workflow
- name: Generate PR comment
if: github.event_name == 'pull_request'
run: vulkro scan . --format gh-pr > vulkro-comment.md
- name: Post PR comment
if: github.event_name == 'pull_request'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh pr comment ${{ github.event.pull_request.number }} --body-file vulkro-comment.md
Monorepo: scan only the affected service
- name: Detect changed services
id: changed
run: |
echo "services=$(git diff --name-only origin/main...HEAD | awk -F/ '/^services\// {print $2}' | sort -u | jq -R . | jq -sc .)" >> $GITHUB_OUTPUT
- name: Scan changed services
run: |
for svc in $(echo '${{ steps.changed.outputs.services }}' | jq -r .[]); do
vulkro scan "services/$svc" --format sarif > "vulkro-$svc.sarif"
done
- name: Upload SARIFs
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: .
Air-gapped self-hosted runners
If your runner can't reach vulkro.com, mirror the binary
internally and set:
- name: Install vulkro (internal mirror)
run: |
curl -fsSL https://artifacts.internal/vulkro/install.sh | bash
env:
VULKRO_OFFLINE: "1"
VULKRO_CDN_BASE_URL: "https://artifacts.internal/vulkro-cve"