CI/CD Integration
Vekt integrates into any CI/CD pipeline via the CLI. The typical pattern is to run vekt scan . (or the planned vekt ci command) as a pipeline step and let the exit code determine whether the build passes.
Table of contents
- Exit codes
- GitHub Actions
- GitLab CI
- Generic CI usage
- SARIF output for GitHub Advanced Security
- Blocking PRs on new findings
- README badge
Exit codes
| Code | Meaning |
|---|---|
0 |
Scan completed with no findings |
1 |
Scan completed and findings were detected |
2 |
Error (parse failure, network error, invalid arguments) |
Use --malicious-only if you want the build to fail only on confirmed malicious packages and not on CVEs.
GitHub Actions
Basic workflow
name: Supply chain scan
on:
push:
branches: [main]
pull_request:
jobs:
vekt:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Vekt
run: |
curl -fsSL https://kief.dev/vekt/install.sh | sh
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
- name: Scan dependencies
run: vekt scan . --quiet
env:
VEKT_API_KEY: ${{ secrets.VEKT_API_KEY }}
Fail on high severity only
- name: Scan dependencies
run: vekt scan . --quiet
env:
VEKT_API_KEY: ${{ secrets.VEKT_API_KEY }}
# vekt ci --fail-on high is coming soon
# Until then, combine with --malicious-only for the strictest check:
# run: vekt scan . --malicious-only --quiet
Separate malicious and vulnerability checks
- name: Check for malicious packages (blocking)
run: vekt scan . --malicious-only --quiet
env:
VEKT_API_KEY: ${{ secrets.VEKT_API_KEY }}
- name: Check for vulnerabilities (non-blocking)
run: vekt scan . --quiet || true
env:
VEKT_API_KEY: ${{ secrets.VEKT_API_KEY }}
Upload JSON results as artifact
- name: Scan dependencies
id: vekt
run: |
vekt scan . --json > vekt-results.json
exit_code=$?
echo "exit_code=$exit_code" >> "$GITHUB_OUTPUT"
exit $exit_code
env:
VEKT_API_KEY: ${{ secrets.VEKT_API_KEY }}
continue-on-error: true
- name: Upload scan results
uses: actions/upload-artifact@v4
with:
name: vekt-results
path: vekt-results.json
- name: Fail if findings detected
if: steps.vekt.outputs.exit_code == '1'
run: exit 1
GitLab CI
vekt-scan:
stage: test
image: ubuntu:24.04
before_script:
- apt-get update -qq && apt-get install -y -qq curl
- curl -fsSL https://kief.dev/vekt/install.sh | sh
- export PATH="$HOME/.local/bin:$PATH"
script:
- vekt scan . --quiet
variables:
VEKT_API_KEY: $VEKT_API_KEY
artifacts:
when: always
reports:
# SARIF support coming soon via vekt ci --sarif
# For now, capture JSON output
paths:
- vekt-results.json
expire_in: 7 days
allow_failure: false
To capture findings as a JSON artifact:
script:
- vekt scan . --json > vekt-results.json; VEKT_EXIT=$?
- exit $VEKT_EXIT
Generic CI usage
Any CI system that can run shell commands works. The pattern is the same:
- Install the
vektbinary - Set
VEKT_API_KEYfrom a secret - Run
vekt scan . - The exit code drives pass/fail
# Install
curl -fsSL https://kief.dev/vekt/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
# Scan
VEKT_API_KEY="$VEKT_API_KEY" vekt scan . --quiet
Using vekt ci (coming soon)
The vekt ci command is planned and will provide a cleaner interface for CI use:
# Fail on any finding at or above HIGH severity
vekt ci --fail-on high
# Fail only on malicious packages
vekt ci --fail-on malicious
# Generate SARIF for GitHub Advanced Security
vekt ci --sarif > vekt.sarif
Until vekt ci ships, use vekt scan directly.
SARIF output for GitHub Advanced Security
Coming soon via vekt ci --sarif.
Once available, SARIF output can be uploaded to GitHub Advanced Security to surface findings in the Security tab and annotate pull requests:
- name: Vekt supply chain scan
run: vekt ci --sarif > vekt.sarif
continue-on-error: true
env:
VEKT_API_KEY: ${{ secrets.VEKT_API_KEY }}
- name: Upload SARIF results
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: vekt.sarif
category: supply-chain
Blocking PRs on new findings
To fail only on findings that are new in a PR (not pre-existing), use vekt diff once it ships. Until then, the recommended approach is to run vekt scan . on every PR and treat exit code 1 as a blocking check.
Coming soon -- vekt diff <base-lockfile> <head-lockfile> will compare two lockfile states and report only net-new findings, making it suitable for incremental PR checks that do not block on pre-existing debt.
README badge
Coming soon on Team and Enterprise plans.
Once available, generate a badge SVG for your README:
# Generate badge URL for your repository
vekt ci --badge
# Outputs: https://kief.dev/vekt/badge/<token>.svg
Embed in your README:

The badge reflects the most recent scan result. It updates whenever you run vekt ci in your pipeline.
Tips
Cache the binary between runs. The vekt binary is a single static file. Cache ~/.local/bin/vekt in your CI cache to avoid re-downloading on every run.
Pin the version. Use a versioned install URL (https://kief.dev/vekt/releases/v0.1.0/vekt-linux-x86_64) in production pipelines rather than latest to avoid unexpected behavior changes.
Store the API key as a secret. Never hardcode the key in workflow files. Use your CI platform's secret store (${{ secrets.VEKT_API_KEY }} in GitHub Actions, CI/CD variables in GitLab, etc.).
Use --quiet in cron scans. If you run a scheduled nightly scan in addition to PR checks, --quiet suppresses output when the project is clean, keeping your logs readable.