Antoine Duno
Founder of ZeriFlow · 10 years fullstack engineering · About the author
Key Takeaways
- Shifting security left into your CI/CD pipeline catches vulnerabilities before they reach production. This guide covers 8 tools that integrate with GitHub Actions, what each one scans, and how to combine them into a pipeline that catches the full stack of security issues without becoming a bottleneck.
- Includes copy-paste code examples and step-by-step instructions.
- Free automated scan available to verify your implementation.
Best CI/CD Security Tools for GitHub Actions in 2026
"Shift left" has become the default framing for application security: catch vulnerabilities early in the development process, when they''re cheap to fix, rather than in production, when they''re expensive and embarrassing.
CI/CD pipelines are where shift-left security becomes operational. A well-configured GitHub Actions pipeline runs security checks on every pull request, fails the build when serious issues are found, and prevents vulnerable code from reaching production.
The challenge is that no single tool covers the full attack surface. Website configuration, application code, dependencies, container images, infrastructure-as-code, and secrets all require different scanning approaches. This guide covers the 8 tools that cover those layers, how each one integrates with GitHub Actions, and how to compose them into a pipeline that''s effective without being painfully slow.
The CI/CD Security Stack at a Glance
| Tool | What It Scans | When It Runs |
|---|---|---|
| ZeriFlow | Live website security (headers, SSL, cookies) | Post-deploy |
| Snyk | Code, dependencies, containers, IaC | On PR, on push |
| CodeQL | Source code (SAST) | On PR, on push |
| Trivy | Container images, filesystems, repos | On PR, on push |
| Checkov | Terraform, CloudFormation, Kubernetes | On PR, on push |
| TruffleHog | Secrets in code and git history | On every commit |
| Dependabot | Dependency updates and CVEs | Continuous (automated PRs) |
| OWASP Dependency-Check | Dependency CVEs (multi-language) | On PR, on push |
Tool 1: ZeriFlow — Website Security in CI/CD
What it scans: Your deployed application — headers, SSL, cookies, mixed content, open ports, information disclosure.
ZeriFlow is the tool in this list that checks what your application looks like from the outside after deployment. All other tools in this guide scan your code and infrastructure before or during deployment. ZeriFlow checks the deployed result.
This matters because many security issues only appear in production. A CDN configuration that strips HSTS headers. A Vercel build that sets headers differently than development. A reverse proxy that adds X-Powered-By headers you removed in application code. These are invisible to static analysis but immediately visible to a scanner that checks the live URL.
Integration pattern: Block PRs when security score drops
The most effective ZeriFlow CI/CD integration runs after a preview deployment is created and checks the deployed preview URL. If the security score drops below a threshold, the pipeline fails and the PR is blocked.
# .github/workflows/security-scan.yml
name: Website Security Check
on:
deployment_status:
jobs:
security_scan:
name: ZeriFlow Security Scan
runs-on: ubuntu-latest
if: github.event.deployment_status.state == ''success''
steps:
- name: Run ZeriFlow Security Scan
id: scan
run: |
RESPONSE=$(curl -s -X POST https://api.zeriflow.com/v1/scans \\
-H "Authorization: Bearer ${{ secrets.ZERIFLOW_API_KEY }}" \\
-H "Content-Type: application/json" \\
-d "{\\"url\\": \\"${{ github.event.deployment_status.target_url }}\\", \\"full_scan\\": true}")
SCORE=$(echo $RESPONSE | jq -r ''.score'')
SCAN_ID=$(echo $RESPONSE | jq -r ''.id'')
echo "Security score: $SCORE/100"
echo "score=$SCORE" >> $GITHUB_OUTPUT
echo "scan_id=$SCAN_ID" >> $GITHUB_OUTPUT
- name: Fail if score below threshold
run: |
if [ "${{ steps.scan.outputs.score }}" -lt "70" ]; then
echo "Security score ${{ steps.scan.outputs.score }}/100 is below the minimum threshold of 70"
exit 1
fi
echo "Security scan passed: ${{ steps.scan.outputs.score }}/100"Baseline comparison pattern: A more sophisticated integration compares the PR branch score against the main branch score and blocks if the PR would cause a regression:
- name: Compare scores against baseline
run: |
# Get baseline (main branch) score
BASELINE=$(curl -s "https://api.zeriflow.com/v1/sites/YOUR_SITE_ID/latest-score" \\
-H "Authorization: Bearer ${{ secrets.ZERIFLOW_API_KEY }}" | jq -r ''.score'')
PR_SCORE="${{ steps.scan.outputs.score }}"
if [ "$PR_SCORE" -lt "$((BASELINE - 5))" ]; then
echo "Security regression detected: main=$BASELINE, PR=$PR_SCORE"
exit 1
fiPricing: Free (Quick Scan) / Pro €9.99/mo (API access for CI/CD integration)
Tool 2: Snyk — Code, Dependencies, Containers, and IaC
What it scans: Vulnerabilities in open source dependencies, application code, Dockerfiles, and IaC files.
Snyk is the most versatile tool on this list in terms of what it covers. A single Snyk integration can scan npm/pip/maven dependencies, find code-level security issues (SQL injection, hardcoded secrets), analyze Dockerfiles for base image vulnerabilities, and check Terraform files for misconfigurations.
# .github/workflows/snyk.yml
name: Snyk Security
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
snyk:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Snyk to check for vulnerabilities
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
args: --severity-threshold=high --fail-on=all
- name: Run Snyk Container scan
uses: snyk/actions/docker@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
with:
image: your-app:latest
args: --severity-threshold=criticalKey configuration decisions:
- --severity-threshold=high blocks on high and critical CVEs only. Starting with critical is less disruptive when first adding Snyk to an existing codebase with known issues.
- --fail-on=all blocks the pipeline on any vulnerability at or above the threshold, including upgradable ones. --fail-on=upgradable is a gentler alternative.
Pricing: Free (open source projects, limited scans) / $25+/user/mo (teams)
Tool 3: CodeQL — Static Application Security Testing
What it scans: Source code for security vulnerabilities — SQL injection, XSS, path traversal, insecure deserialization, hardcoded credentials.
GitHub''s CodeQL is a SAST (Static Application Security Testing) engine that analyzes the logic of your code rather than just its syntax. It''s free for public repositories and available on GitHub Advanced Security for private repositories.
# .github/workflows/codeql.yml
name: CodeQL
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
- cron: ''30 1 * * 1'' # Weekly scan
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
matrix:
language: [''javascript'', ''typescript'']
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
queries: security-and-quality
- name: Autobuild
uses: github/codeql-action/autobuild@v3
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{ matrix.language }}"What `security-and-quality` queries catch: - SQL injection via string concatenation - XSS through unsanitized DOM manipulation - Path traversal in file operations - Prototype pollution vulnerabilities - Regular expression denial of service (ReDoS) - Insecure JWT verification
Pricing: Free for public repos / Included in GitHub Advanced Security for private repos ($49/user/mo or per-repository pricing for Enterprise)
Tool 4: Trivy — Container and Filesystem Scanning
What it scans: Container images, filesystem vulnerabilities, IaC misconfigurations, and exposed secrets.
Trivy is a comprehensive open source scanner from Aqua Security. It''s fast, well-maintained, and covers more ground than most other container security tools. For teams running Docker containers, it''s the standard choice for CI/CD.
# .github/workflows/trivy.yml
name: Trivy Security Scan
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
trivy:
name: Trivy Container Scan
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t app:${{ github.sha }} .
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
image-ref: ''app:${{ github.sha }}''
format: ''sarif''
output: ''trivy-results.sarif''
severity: ''CRITICAL,HIGH''
exit-code: ''1''
- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: ''trivy-results.sarif''Uploading results as SARIF pushes findings to the GitHub Security tab, where they''re visible alongside CodeQL findings in a unified interface.
Pricing: Free (open source)
Tool 5: Checkov — Infrastructure as Code Security
What it scans: Terraform, CloudFormation, Kubernetes manifests, Dockerfiles, and other IaC files.
Infrastructure misconfigurations — S3 buckets with public access, security groups with unrestricted inbound rules, databases without encryption — are a leading cause of cloud data breaches. Checkov catches these in code before they''re deployed.
# .github/workflows/checkov.yml
name: Checkov IaC Scan
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
checkov:
name: Checkov Infrastructure Security
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Run Checkov
uses: bridgecrewio/checkov-action@master
with:
directory: ./infrastructure # or ./terraform, ./k8s
framework: terraform # or cloudformation, kubernetes, dockerfile
output_format: sarif
output_file_path: checkov-results.sarif
soft_fail: false
skip_check: CKV_AWS_118,CKV2_AWS_62 # example: skip specific checks
- name: Upload results to GitHub Security
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: checkov-results.sarifCommon findings Checkov catches:
- AWS S3 bucket public access not blocked
- Security groups with 0.0.0.0/0 inbound on sensitive ports
- RDS instances without encryption at rest
- CloudTrail logging disabled
- IAM policies with overly broad permissions (* actions or resources)
- EKS clusters without private endpoint
Pricing: Free (open source) / Paid SaaS for Bridgecrew/Prisma Cloud
Tool 6: TruffleHog — Secret Detection
What it scans: Hardcoded secrets in code and git history — API keys, passwords, tokens, certificates.
Hardcoded secrets are one of the most common causes of serious security incidents. A developer accidentally commits an AWS access key, a database password, or a Stripe secret key. The secret ends up in git history, where it can be discovered by anyone with read access to the repository — including attackers who compromise a developer''s GitHub account.
TruffleHog scans the diff in every PR for high-entropy strings that match patterns for known secret types.
# .github/workflows/trufflehog.yml
name: TruffleHog Secret Scan
on:
push:
pull_request:
jobs:
trufflehog:
name: TruffleHog
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0 # Full history for --since-commit
- name: Run TruffleHog
uses: trufflesecurity/trufflehog@main
with:
path: ./
base: ${{ github.event.repository.default_branch }}
head: HEAD
extra_args: --debug --only-verified--only-verified reduces false positives by only flagging secrets that TruffleHog can verify are active (it attempts to call the API/service with the discovered secret). This is more invasive but dramatically more actionable.
Pricing: Free (open source) / TruffleHog Enterprise for team features
Tool 7: Dependabot — Automated Dependency Updates
What it scans: npm, pip, maven, and other package manager dependencies for CVEs and outdated versions.
Dependabot is built into GitHub and runs automatically without any workflow configuration. A single .github/dependabot.yml file enables it:
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 10
labels:
- "dependencies"
reviewers:
- "your-username"
ignore:
# Ignore major version bumps that might break things
- dependency-name: "next"
update-types: ["version-update:semver-major"]
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"Dependabot creates PRs for security advisories immediately (regardless of the schedule) and for regular updates on your configured schedule. Your existing CI/CD pipeline runs against Dependabot PRs the same as any developer PR.
Pricing: Free for GitHub repositories
Tool 8: OWASP Dependency-Check — Multi-Language CVE Scanning
What it scans: Java, .NET, Python, Ruby, Node.js, and other language dependencies against the NVD (National Vulnerability Database).
For polyglot repositories or Java/JVM projects where Snyk''s depth on Maven and Gradle dependencies is important, OWASP Dependency-Check is the standard. For pure Node.js projects, npm audit and Snyk cover the same ground.
# .github/workflows/dependency-check.yml
name: OWASP Dependency Check
on:
push:
branches: [main]
schedule:
- cron: ''0 6 * * 1'' # Weekly
jobs:
dependency-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run OWASP Dependency Check
uses: dependency-check/Dependency-Check_Action@main
with:
project: ''your-project''
path: ''.''
format: ''HTML''
args: >
--failOnCVSS 7
--enableRetired
- name: Upload results
uses: actions/upload-artifact@v4
with:
name: Dependency-Check-Report
path: ${{ github.workspace }}/reportsPricing: Free (open source)
Building the Complete Pipeline
Pipeline Architecture
The key to a useful security pipeline is structuring it so fast checks run first and expensive checks don''t block developer velocity:
# Suggested pipeline structure
stages:
fast_checks: # < 60 seconds
- TruffleHog (secrets scan on diff only)
- ESLint security plugin (already in lint stage)
- npm audit (built-in, fast)
medium_checks: # 1-5 minutes
- Snyk (dependency and code)
- Checkov (IaC)
- Dependabot PRs (passive, no blocking)
deep_checks: # 5-15 minutes
- CodeQL (SAST)
- Trivy (container)
- OWASP Dependency-Check (weekly)
post_deploy: # After preview deployment
- ZeriFlow (live website scan)Which Tools to Prioritize
If you''re adding CI/CD security tools to an existing pipeline, start with the highest value-to-effort ratio:
- 1TruffleHog — highest urgency, lowest effort, irreversible damage from secrets in git
- 2Dependabot — one config file, runs automatically, addresses the most common vulnerability source
- 3ZeriFlow — covers website security that static analysis misses, free tier available
- 4Snyk — comprehensive dependency and code scanning with good free tier
- 5CodeQL — free for public repos, thorough SAST for private repos with GitHub Advanced Security
- 6Trivy — if you''re shipping containers
- 7Checkov — if you''re writing IaC
Managing Pipeline Friction
Security tools in CI/CD only work if developers don''t route around them. If scans take 15 minutes and produce 50 findings for every PR, developers will start disabling them.
Practical guidelines:
- Start tools in --soft-fail or advisory mode, then transition to blocking after the team has cleared the backlog of existing issues
- Set realistic thresholds — blocking on CRITICAL first, then HIGH, rather than everything at once
- Parallelize scans — most of these tools can run concurrently
- Skip expensive scans on draft PRs
- Cache scan results for unchanged files
The goal is a pipeline that catches real issues without becoming friction that undermines the shipping velocity that makes security investments sustainable.
Start with ZeriFlow''s free scan on your production URL at zeriflow.com/free-scan to see your current website security posture — then work backward to which pipeline tools would have caught those issues before deployment.
Add security scanning to your CI/CD pipeline.
Catch vulnerabilities before they reach production.