A GitHub Actions CI/CD security pipeline built from scratch with zero 3rd-party actions — a deliberate supply-chain hardening decision.
The pipeline targets OWASP Juice Shop as its intentionally vulnerable application, demonstrating end-to-end container security scanning integrated directly into the build process.
git fetch (manual, no actions/checkout)
│
▼
Docker build
juice-shop:$SHA
│
├──► Syft ──► SBOM (CycloneDX JSON + SPDX)
│
├──► Grype ──► Vulnerability scan (JSON + SARIF)
│
└──► Quality Gate (bash/jq)
│
├── PASS → commit reports to branch
└── FAIL → exit 1 (build blocked)
| Decision | Rationale |
|---|---|
| Zero 3rd-party GitHub Actions | Eliminates supply-chain attack surface (compromised actions in CI are a known vector — e.g., tj-actions/changed-files incident) |
| CycloneDX JSON SBOM | Industry-standard format (NTIA-compliant), machine-parseable, supports downstream vulnerability correlation |
| SARIF output | Standard format for security tool results; compatible with GitHub Security tab and external SIEM ingestion |
| Configurable severity threshold | Quality gate accepts none|low|medium|high|critical — allows teams to tune acceptable risk per environment (dev vs. prod) |
[skip ci] on report commits |
Prevents infinite pipeline loop when workflow commits scan results back to the repo |
| Tool | Role | Output Format |
|---|---|---|
| Syft | SBOM generation | CycloneDX JSON, SPDX |
| Grype | Vulnerability scanning (CVE matching against SBOM) | JSON, SARIF |
| Docker | Image build | — |
| bash + jq | Quality gate logic | Exit code (0 = pass, 1 = fail) |
The pipeline enforces a configurable severity threshold. Set SEVERITY_THRESHOLD in the workflow:
env:
SEVERITY_THRESHOLD: high # none | low | medium | high | criticalIf any finding meets or exceeds the threshold, the pipeline exits with code 1, blocking the build. This mirrors production-grade security gate behavior in enterprise DevSecOps environments.
.github/workflows/devsecops-noapi.yml
mustafkgl/juice-shop — OWASP Juice Shop, an intentionally vulnerable Node.js application. Used here as a realistic pipeline target: a real-world application with known CVEs in its dependency tree, demonstrating that the quality gate correctly identifies and blocks on actual vulnerability data.
mustafkgl/secure-container-lab— Container hardening companion project: reduces a Node.js image from 1,675 to 12 CVEs using Distroless base images, multi-stage builds, and runtime hardening.