Skip to content

CI/CD Security: SAST, DAST, Sigstore, SBOM & Provenance

Chapter 37: CI/CD Security: SAST, DAST, Sigstore, SBOM & Provenance

Section titled “Chapter 37: CI/CD Security: SAST, DAST, Sigstore, SBOM & Provenance”
  • Implement security gates at every stage of the CI/CD pipeline
  • Perform SAST (Static), DAST (Dynamic), and SCA (Dependency) scanning
  • Sign container images with Sigstore/Cosign
  • Generate and verify SBOM for supply chain security

CI/CD security secures the automated pipelines that build and deploy software. If a hacker breaches the deployment pipeline, they can secretly inject malicious code into the product before it even reaches the users. This secures the software supply chain.

Security Gates in CI/CD
────────────────────────
Code Push → Build → Test → Package → Deploy → Runtime
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
Pre-commit SAST DAST Image Runtime
hooks lint scan signing monitoring
secret scan SCA OWASP SBOM Falco
(gitleaks) CVE ZAP Cosign OPA
Shift Left: Find vulnerabilities as early as possible
Pre-commit hooks are 1000x cheaper than production fixes

37.2 SAST: Static Application Security Testing

Section titled “37.2 SAST: Static Application Security Testing”
Terminal window
# ── Semgrep: Multi-language SAST ──────────────────────────
pip install semgrep
# Scan with OWASP ruleset
semgrep --config=p/owasp-top-ten ./src/
# Scan for specific patterns
semgrep --config=p/secrets ./ # Detect hardcoded secrets
semgrep --config=p/python ./ # Python-specific issues
semgrep --config=p/docker ./ # Dockerfile issues
# CI integration
semgrep ci --config=p/ci # Auto-detects repo, fails on findings
# ── Bandit: Python Security ───────────────────────────────
pip install bandit
bandit -r ./src/ -ll # -ll = medium+ severity
# ── CodeQL (GitHub): Deep analysis ────────────────────────
# .github/workflows/codeql.yml
# uses: github/codeql-action/analyze@v2
# languages: [python, javascript, go]
# ── Gitleaks: Secret Detection ────────────────────────────
gitleaks detect --source . --verbose
gitleaks protect --staged # Pre-commit hook
# Pre-commit config: .pre-commit-config.yaml
repos:
- repo: https://github.com/zricethezav/gitleaks
rev: v8.18.0
hooks:
- id: gitleaks
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.8.0
hooks:
- id: mypy

37.3 SCA: Software Composition Analysis (Dependency Scanning)

Section titled “37.3 SCA: Software Composition Analysis (Dependency Scanning)”
Terminal window
# ── Trivy: Vulnerability scanning ────────────────────────
# Scan filesystem (dependencies)
trivy fs --security-checks vuln,secret ./
# Scan Docker image
trivy image --severity HIGH,CRITICAL myapp:latest
# Scan Kubernetes cluster
trivy k8s --report summary all
# ── OWASP Dependency-Check ────────────────────────────────
dependency-check --project "MyApp" --scan ./ --format HTML
# ── pip-audit (Python) ────────────────────────────────────
pip-audit -r requirements.txt
# ── npm audit (Node.js) ───────────────────────────────────
npm audit --audit-level=high
# ── GitHub Dependabot (automated PRs) ────────────────────
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: pip
directory: "/"
schedule:
interval: weekly
open-pull-requests-limit: 10
- package-ecosystem: docker
directory: "/"
schedule:
interval: weekly

37.4 Container Image Signing with Sigstore/Cosign

Section titled “37.4 Container Image Signing with Sigstore/Cosign”
Supply Chain Attack Problem
────────────────────────────
Attacker compromises registry → Pushes malicious image
Developer pulls "latest" → Runs malicious code
Sigstore/Cosign Solution:
──────────────────────────
Build image → Sign with private key → Push signature to registry
Deploy time → Verify signature → Only trusted images run
Sigstore advantages:
✓ Keyless signing (uses OIDC identity from GitHub/GitLab)
✓ Transparency log (Rekor) — tamper-evident, public audit log
✓ No key management required (ephemeral keys)
Terminal window
# Install cosign
curl -O -L "https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64"
chmod +x cosign-linux-amd64 && mv cosign-linux-amd64 /usr/local/bin/cosign
# ── Keyless Signing (OIDC-based) ──────────────────────────
# In GitHub Actions:
- name: Sign image with Cosign
uses: sigstore/cosign-installer@v3
- name: Sign the image
env:
COSIGN_EXPERIMENTAL: 1 # Keyless mode
run: |
cosign sign --yes ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}
# ── Verify signature ──────────────────────────────────────
# Verify image was signed by GitHub Actions from specific repo:
cosign verify \
--certificate-oidc-issuer=https://token.actions.githubusercontent.com \
--certificate-identity=https://github.com/myorg/myrepo/.github/workflows/build.yml@refs/heads/main \
myregistry.io/myapp@sha256:abc123...
# ── Kyverno policy: Only allow signed images ──────────────
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-image-signature
spec:
validationFailureAction: Enforce
rules:
- name: verify-signature
match:
any:
- resources:
kinds: [Pod]
verifyImages:
- imageReferences: ["myregistry.io/*"]
attestors:
- entries:
- keyless:
subject: "https://github.com/myorg/myrepo/*"
issuer: "https://token.actions.githubusercontent.com"

Terminal window
# Generate SBOM with Syft
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh
# Generate SBOM for a container image
syft myapp:latest -o cyclonedx-json > sbom.json
syft myapp:latest -o spdx-json > sbom.spdx.json
# Attach SBOM to image (stored in registry)
cosign attach sbom --sbom sbom.json myapp@sha256:abc123...
# Generate SBOM for filesystem
syft dir:./src -o spdx-json > app-sbom.json
# Scan SBOM for vulnerabilities
grype sbom:sbom.json
# ── What's in an SBOM? ────────────────────────────────────
# Component list: name, version, supplier, license, checksums
# Relationships: which component depends on which
# Metadata: tool used, timestamp, format version
#
# Use cases:
# • Compliance: know all licenses in use
# • Vulnerability tracking: when Log4Shell hits, find all apps using log4j
# • Supply chain: verify what went into the image

.github/workflows/secure-build.yml
name: Secure Build and Deploy
on:
push:
branches: [main]
permissions:
contents: read
packages: write
id-token: write # For keyless signing
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# SAST
- name: Run Semgrep
uses: semgrep/semgrep-action@v1
with:
config: p/owasp-top-ten
# Secret detection
- name: Run Gitleaks
uses: gitleaks/gitleaks-action@v2
# Dependency scanning
- name: Run pip-audit
run: pip-audit -r requirements.txt
build:
needs: security
runs-on: ubuntu-latest
outputs:
digest: ${{ steps.build.outputs.digest }}
steps:
- uses: actions/checkout@v4
- name: Build image
id: build
uses: docker/build-push-action@v5
with:
push: true
tags: ghcr.io/${{ github.repository }}:${{ github.sha }}
# Container vulnerability scan
- name: Run Trivy
uses: aquasecurity/trivy-action@master
with:
image-ref: ghcr.io/${{ github.repository }}:${{ github.sha }}
exit-code: '1'
severity: CRITICAL
# Generate SBOM
- name: Generate SBOM
uses: anchore/sbom-action@v0
with:
image: ghcr.io/${{ github.repository }}:${{ github.sha }}
# Sign image
- name: Install Cosign
uses: sigstore/cosign-installer@v3
- name: Sign image
run: |
cosign sign --yes \
ghcr.io/${{ github.repository }}@${{ steps.build.outputs.digest }}

Q1: What is the difference between SAST and DAST?

Answer: SAST (Static Application Security Testing) analyzes source code or compiled bytecode without running the application. It finds: SQL injection patterns, hardcoded secrets, insecure function calls, buffer overflows, deserialization issues. Runs during development (pre-commit, CI) — catches issues early. DAST (Dynamic Application Security Testing) tests the running application by sending malicious input and observing responses. Tools: OWASP ZAP, Burp Suite. It finds: actual exploitable vulnerabilities, runtime behavior issues, authentication bypasses. DAST runs against a deployed environment (staging). The combination: SAST for code quality and known patterns, DAST for actual exploitability in the running app.

Q2: What is an SBOM and why is it important for supply chain security?

Answer: An SBOM (Software Bill of Materials) is a complete inventory of all components in a software package — libraries, frameworks, dependencies, versions, licenses, and their checksums. It’s important for supply chain security because: (1) Vulnerability response: When Log4Shell (CVE-2021-44228) hit, organizations with SBOMs could instantly identify which of their applications used log4j. Without SBOM, they spent weeks auditing. (2) License compliance: Know all open-source licenses in use (GPL, MIT, Apache). (3) Attack surface: Understand what’s in your container image. (4) US Executive Order 14028 now requires SBOMs for software sold to the US government. Generate with: Syft, Trivy. Formats: CycloneDX, SPDX.


Security StageTool
Pre-commitGitleaks (secrets), pre-commit hooks
Code (SAST)Semgrep, Bandit, CodeQL
Dependencies (SCA)Trivy, pip-audit, npm audit
Container scanTrivy, Snyk
Image signingCosign (Sigstore)
SBOMSyft, Trivy
Admission controlKyverno verify-images policy

CI/CD basics, Chapter 35 (Container Security).


Advantages: Catches vulnerabilities before production, guarantees artifact integrity (SBOMs/Sigstore). Disadvantages: Security scans slow down developer pipelines, false positives cause friction.


  • Hardcoding deployment credentials in pipeline scripts.
  • Skipping security scans to make the pipeline faster.
  • Allowing any developer to trigger deployments to production without review (no branch protection).

SymptomCauseDiagnosisFix
Pipeline fails on SAST stepCode contains a vulnerability (e.g., SQL injection)Review SAST tool output in pipeline logsFix the code vulnerability and push again
Deployment fails due to bad signatureImage signing failed or verification blocked itCheck Sigstore/Cosign logsEnsure the image was signed correctly in the CI phase

Objective: Generate an SBOM.

Terminal window
# 1. Install Syft
# curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh
# 2. Generate SBOM for an image
# syft ubuntu:latest -o json > sbom.json
# 3. Inspect the SBOM
cat sbom.json | grep -i "name\|version" | head -20

  1. Integrate a secret scanner (like trufflehog or gitleaks) into a mock GitHub Actions workflow.
  2. Use cosign to generate a keypair, sign a Docker image, and verify the signature.

  • SAST (Static) analyzes code; DAST (Dynamic) analyzes running apps.
  • SCA (Software Composition Analysis) finds vulnerabilities in third-party dependencies.
  • SBOM (Software Bill of Materials) is an inventory of all components in an artifact.
  • Sigstore/Cosign ensures artifact integrity via cryptographic signatures.

  • SLSA Framework (slsa.dev)
  • OWASP DevSecOps Guideline


Last Updated: July 2026