"CI/CD Vulnerability Scanning with GitHub Actions: 5-Minute Setup (2026)"
How to integrate vulnerability scanning into CI/CD in 5 minutes. One copy-paste GitHub Actions workflow that scans every pull request, fails the build on critical CVEs, and generates an SBOM automatically.
Quick Answer: How to Add Vulnerability Scanning to CI/CD
Integrate vulnerability scanning into your CI/CD pipeline with one YAML file. Add .github/workflows/vulnledger.yml to your repository:
name: Security Scan
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
security-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip install vulnledger
- run: vulnledger scan . --ci
The --ci flag fails the build on critical or high CVEs. Every push and pull request is scanned automatically — no manual security reviews needed. The scan runs in ~1 minute, covers Python, Go, Rust, and JavaScript dependencies, and generates an SBOM at the same time.
Security scanning in CI/CD used to require complex tool chains — Snyk, Trivy, Grype, Dependabot, all configured separately. One YAML file with VulnLedger gives you SBOM generation, vulnerability scanning, and a build gate that fails on critical CVEs. Here's exactly how to set it up in under 5 minutes.
Quick Start: Copy This Into Your Repo
Create .github/workflows/vulnledger.yml in your repository:
name: Security Scan
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
security-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install VulnLedger CLI
run: pip install vulnledger
- name: Run security scan
run: vulnledger scan . --ci
That's it. Every push and pull request is now scanned for vulnerabilities. The --ci flag fails the build if critical or high CVEs are found.
Why CI/CD Security Scanning Matters
Manual security reviews do not scale. As projects grow and teams ship faster, the gap between "last security scan" and "current code" widens. Automated CI/CD scanning closes this gap:
- Every commit gets scanned — no code slips through without security review
- Immediate feedback — developers see vulnerabilities before merging
- Consistent enforcement — policies apply to every pull request, not just when someone remembers
- Audit trail — every scan result is logged with commit hash and timestamp
- Shift-left security — fix vulnerabilities when they are cheapest to fix (during development)
The CI/CD Security Pipeline
A complete CI/CD security pipeline typically includes these stages:
1. SBOM Generation
Generate a Software Bill of Materials when dependencies change. The SBOM captures every component your project depends on — direct and transitive.
2. Vulnerability Scanning
Check every component in your SBOM against known vulnerability databases (OSV, NVD, GitHub Advisory Database).
3. Policy Enforcement
Compare scan results against your security policies. Should any critical vulnerabilities block deployment? What about license compliance?
4. Reporting and Alerts
Notify the team about new vulnerabilities, policy violations, and compliance status.
GitHub Actions Workflow: Basic Setup
Here is a minimal GitHub Actions workflow that generates an SBOM and scans for vulnerabilities on every push:
name: Security Scan
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
security-scan:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install VulnLedger CLI
run: pip install vulnledger
- name: Run SBOM generation and scan
run: vulnledger scan --format cyclonedx --output sbom.json
- name: Upload SBOM artifact
uses: actions/upload-artifact@v4
with:
name: sbom
path: sbom.json
This workflow runs on every push and pull request to main. It generates a CycloneDX SBOM and uploads it as a build artifact.
Advanced Workflow: Policy Enforcement
For production use, you want to fail the build when critical vulnerabilities are found:
name: Security Gate
on:
pull_request:
branches: [main]
jobs:
security-gate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install VulnLedger CLI
run: pip install vulnledger
- name: Scan for vulnerabilities
run: vulnledger scan --output report.json --format cyclonedx
continue-on-error: true
- name: Check security gate
run: |
CRITICAL=$(python3 -c "import json; d=json.load(open('report.json')); print(d.get('summary',{}).get('critical',0))")
if [ "$CRITICAL" -gt 0 ]; then
echo "FAIL: $CRITICAL critical vulnerabilities found"
echo "Fix critical vulnerabilities before merging"
exit 1
fi
echo "PASS: No critical vulnerabilities"
- name: Upload report
uses: actions/upload-artifact@v4
if: always()
with:
name: security-report
path: report.json
This workflow blocks pull requests that introduce critical vulnerabilities while allowing non-critical issues to pass with a warning.
Multi-Language Support
Modern projects often use multiple programming languages. GitHub Actions can scan all of them:
name: Multi-Language Security Scan
on:
push:
branches: [main]
jobs:
scan-python:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip install vulnledger
- run: vulnledger scan --output python-sbom.json
scan-node:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
- run: npm install
- run: pip install vulnledger
- run: vulnledger scan --output node-sbom.json
scan-go:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: "1.22"
- run: pip install vulnledger
- run: vulnledger scan --output go-sbom.json
Each language gets its own job, and the SBOMs are uploaded as separate artifacts. This parallel approach keeps CI fast while maintaining comprehensive coverage.
Scheduled Scanning
Even code that does not change can become vulnerable when new CVEs are published. Add scheduled scanning to catch these:
name: Scheduled Vulnerability Check
on:
schedule:
- cron: "0 8 * * 1" # Every Monday at 8 AM
jobs:
weekly-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install VulnLedger CLI
run: pip install vulnledger
- name: Full scan with latest vuln data
run: vulnledger scan --output weekly-report.json
- name: Create GitHub issue if critical vulns found
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const report = JSON.parse(fs.readFileSync('weekly-report.json'));
const critical = report.summary?.critical || 0;
if (critical > 0) {
await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: `Weekly Security Alert: ${critical} critical vulnerabilities`,
body: `Weekly scan found ${critical} critical vulnerabilities. Please review and remediate.`,
labels: ['security', 'critical']
});
}
This runs every Monday morning and automatically creates a GitHub issue when critical vulnerabilities are discovered.
Integrating with VulnLedger Dashboard
For teams using VulnLedger's cloud dashboard, you can push scan results directly:
- name: Scan and upload to VulnLedger
env:
VULNLEDGER_API_KEY: ${{ secrets.VULNLEDGER_API_KEY }}
run: |
vulnledger scan --upload --api-key $VULNLEDGER_API_KEY
This sends your SBOM and scan results to VulnLedger's dashboard for centralized tracking, alerting, and compliance reporting across all your projects.
Best Practices
1. Scan on Every Pull Request
Never merge code without scanning it first. Configure your GitHub branch protection rules to require the security scan job to pass before merging.
2. Store SBOMs as Artifacts
Upload SBOMs as GitHub Actions artifacts. This creates an audit trail and lets you compare SBOMs across versions.
3. Use Secrets for API Keys
Never hardcode API keys or tokens in workflow files. Use GitHub Secrets:
env:
VULNLEDGER_API_KEY: ${{ secrets.VULNLEDGER_API_KEY }}
4. Set Timeouts
Security scans should not run forever. Set reasonable timeouts to prevent runaway jobs:
jobs:
security-scan:
runs-on: ubuntu-latest
timeout-minutes: 15
5. Cache Dependencies
Cache pip packages and other dependencies to speed up your security scans:
- name: Cache pip
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}
6. Fail Loud
When a security issue is found, make it obvious. Use clear error messages, appropriate exit codes, and visible annotations:
- name: Annotate PR with vulnerabilities
if: failure()
run: |
echo "::error::Critical vulnerabilities found. See scan report for details."
Common Pitfalls
Scanning only on main branch — You need to scan pull requests too, not just after merging. Scanning only on main means vulnerabilities get merged first and detected second.
Ignoring transitive dependencies — Direct dependencies get updated, but transitive dependencies (dependencies of your dependencies) are often forgotten. A full SBOM captures all levels.
No scheduled scanning — New CVEs are published daily. A project with zero vulnerabilities today could have critical vulnerabilities tomorrow. Schedule weekly scans.
Overly strict policies — If every build fails, developers will bypass security checks. Start with critical-only blocking and expand gradually.
Getting Started Today
The fastest way to add security scanning to your GitHub Actions pipeline:
# 1. Install the CLI
pip install vulnledger
# 2. Generate your first SBOM locally
vulnledger scan --format cyclonedx
# 3. Review the results
cat sbom.json | python3 -m json.tool | head -50
# 4. Copy the GitHub Actions workflow to your repo
# 5. Push and watch the security scan run automatically
For teams wanting centralized dashboards, alerts, and compliance reporting, VulnLedger's cloud dashboard integrates directly with the CLI. Sign up at vulnledger.com — free for open-source projects.
How VulnLedger Compares to Other CI/CD Security Tools
For a full comparison of CI/CD security tools, see our Dependabot alternatives guide.
| Tool | SBOM | Vuln Scan | CI Gate | Cost |
|---|---|---|---|---|
| VulnLedger | Yes | Yes | Yes | Free |
| Dependabot | No | Yes | No | Free |
| Snyk | Yes | Yes | Yes | $25/dev |
| Trivy | Yes | Yes | Yes | Free |
| Grype | Yes | Yes | Yes | Free |
| Dependency-Track | Yes | Yes | Yes | Free (self-host) |
VulnLedger is the only tool that combines SBOM generation, vulnerability scanning, AND a CI/CD gate in a single command — without requiring Docker or self-hosting.
FAQ
Q: How do I integrate vulnerability scanning into CI/CD?
A: Add a scan step to your pipeline that runs on every push and pull request. With GitHub Actions, copy the Quick Answer workflow above into .github/workflows/vulnledger.yml. The --ci flag fails the build on critical or high CVEs, and the scan runs in about a minute.
Q: What is the best vulnerability scanner for GitHub Actions?
A: VulnLedger is the fastest to set up — one pip install step and one command in your workflow. Trivy and Grype are also free and solid, but both require Docker installed in your runner. Dependabot scans but cannot gate your build.
Q: Should the security scan run on pull requests or only on main?
A: Both. Scan on pull requests to block vulnerable code before it merges, and run a scheduled scan (weekly) to catch newly published CVEs that affect code you already shipped.
Q: What does --ci do in the vulnledger command?
A: It makes the scan exit non-zero when critical or high severity vulnerabilities are found, so your build fails. Remove it if you only want to report issues without blocking deployments.
Q: Does vulnerability scanning slow down CI/CD pipelines?
A: Typically adds 1-3 minutes. VulnLedger runs in a single step without Docker, so it's among the fastest options. Use the cache best practice above to keep pip installs quick.
Conclusion
CI/CD security scanning is no longer optional — it is a baseline requirement for any serious software project. By integrating SBOM generation and vulnerability scanning into GitHub Actions, you get automated security enforcement without slowing down your team. The investment in setup pays for itself the first time a critical vulnerability is caught before reaching production.