Build a DevSecOps Pipeline from Scratch (2026 Project Walkthrough)
A complete end-to-end DevSecOps pipeline with SAST, container scanning, secrets detection, DAST, and supply chain security using open-source tools.
DevSecOps gets thrown around a lot. This guide shows you how to actually build it — a real pipeline with security checks at every stage, using open-source tools on GitHub Actions.
What You Will Build
Code Push → Secret Scan → SAST → Dependency Scan
↓
Docker Build + Container Scan
↓
Image Signing → Deploy Staging
↓
DAST → Deploy Production
Why Security in the Pipeline?
The earlier you catch vulnerabilities, the cheaper they are to fix:
- Found in development: $10 to fix
- Found in staging: $100 to fix
- Found in production: $10,000+ (incident, customer impact, compliance)
Stage 1: Secret Scanning with Gitleaks
Catches hardcoded API keys, passwords, and tokens before they reach your repo history.
- name: Detect secrets with Gitleaks
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}Run this before any other stage. A secret in code invalidates everything downstream.
Stage 2: SAST with Semgrep
Static Application Security Testing analyzes source code without running it. Finds SQL injection, XSS, hardcoded credentials, insecure patterns.
- name: Run Semgrep SAST
uses: semgrep/semgrep-action@v1
with:
config: >-
p/security-audit
p/owasp-top-ten
p/nodejsFree for open-source. 3000+ rules out of the box.
Stage 3: Dependency Scanning
Your code might be clean, but your npm/pip/maven packages might have known CVEs.
- name: OWASP Dependency Check
uses: dependency-check/Dependency-Check_Action@main
with:
project: myapp
path: .
format: SARIF
args: --failOnCVSS 7--failOnCVSS 7 fails the build on HIGH and CRITICAL vulnerabilities.
Stage 4: Container Image Scanning with Trivy
After building the Docker image, scan it before pushing.
- name: Build Docker image
run: docker build -t myapp:${{ github.sha }} .
- name: Scan with Trivy
uses: aquasecurity/trivy-action@master
with:
image-ref: myapp:${{ github.sha }}
format: sarif
output: trivy-results.sarif
severity: CRITICAL,HIGH
exit-code: 1
- name: Push image (only if scan passes)
run: docker push ghcr.io/myorg/myapp:${{ github.sha }}Trivy scans OS packages, language packages, Dockerfile misconfigs, and secrets baked into image layers.
Stage 5: Image Signing with cosign
Proves the image was built by your pipeline and not tampered with.
- name: Install cosign
uses: sigstore/cosign-installer@v3
- name: Sign image (keyless via Sigstore)
run: |
cosign sign --yes ghcr.io/myorg/myapp:${{ github.sha }}Before deploying to production, verify:
cosign verify \
--certificate-identity-regexp="https://github.com/myorg/myapp" \
--certificate-oidc-issuer="https://token.actions.githubusercontent.com" \
ghcr.io/myorg/myapp:abc123If verification fails — image was tampered with or not built by your pipeline.
Stage 6: DAST with OWASP ZAP
Dynamic Application Security Testing runs against the deployed staging environment. Finds auth bypass, injection flaws, and misconfigurations that only appear at runtime.
- name: OWASP ZAP Baseline Scan
uses: zaproxy/action-baseline@v0.12.0
with:
target: https://staging.myapp.com
cmd_options: -aOnly runs after staging deploy. ZAP needs a live target.
Complete Job Structure
name: DevSecOps Pipeline
on:
push:
branches: [main]
jobs:
secret-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
sast:
needs: secret-scan
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: semgrep/semgrep-action@v1
with:
config: p/security-audit p/owasp-top-ten
build-scan:
needs: sast
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: docker build -t myapp:${{ github.sha }} .
- uses: aquasecurity/trivy-action@master
with:
image-ref: myapp:${{ github.sha }}
severity: CRITICAL,HIGH
exit-code: 1
- run: docker push ghcr.io/myorg/myapp:${{ github.sha }}
deploy-staging:
needs: build-scan
environment: staging
runs-on: ubuntu-latest
steps:
- run: echo "Deploy to staging"
dast:
needs: deploy-staging
runs-on: ubuntu-latest
steps:
- uses: zaproxy/action-baseline@v0.12.0
with:
target: https://staging.myapp.com
deploy-production:
needs: dast
environment: production
runs-on: ubuntu-latest
steps:
- run: echo "Deploy to production"What Each Stage Catches
| Stage | Tool | Catches |
|---|---|---|
| Secret scan | Gitleaks | Hardcoded API keys, tokens |
| SAST | Semgrep | SQLi, XSS, insecure patterns |
| Dependency scan | OWASP DC | Known CVEs in packages |
| Container scan | Trivy | OS CVEs, Dockerfile misconfigs |
| Image signing | cosign | Supply chain tampering |
| DAST | OWASP ZAP | Runtime vulnerabilities |
What to Add Next
- Kyverno/OPA — enforce K8s admission policies
- SBOM — generate Software Bill of Materials with
syft - Falco — runtime threat detection in containers
- Checkov — Terraform and Helm security scanning
Resources
Stay ahead of the curve
Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.
Related Articles
Build a DevSecOps Pipeline with Trivy, SonarQube, and OPA from Scratch (2026)
Step-by-step project walkthrough: add security scanning, code quality gates, and policy enforcement to a GitHub Actions pipeline. Real configs, production-ready.
Build a Docker CI/CD Pipeline with GitHub Actions and AWS ECR (2026)
Step-by-step guide to building a production CI/CD pipeline that builds, scans, and pushes Docker images to AWS ECR using GitHub Actions.
GitHub Actions CI/CD Pipeline: Complete Tutorial for Docker & Kubernetes (2026)
Learn how to build a production-grade CI/CD pipeline using GitHub Actions. Covers Docker image builds, automated testing, secrets management, and Kubernetes deployments — with real workflow files.