DEV Community

Citadel Cloud Management
Citadel Cloud Management

Posted on • Originally published at citadelcloudmanagement.com

Building a DevSecOps Pipeline with GitHub Actions: My Production Config

Here is the exact GitHub Actions workflow I use to catch security vulnerabilities before they reach production. Every tool is open source. Total cost: $0.

The Workflow File

name: security-pipeline
on:
  pull_request:
    branches: [main]
  push:
    branches: [main]

jobs:
  secret-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - name: Gitleaks secret detection
        uses: gitleaks/gitleaks-action@v2
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

  dependency-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Trivy vulnerability scan
        uses: aquasecurity/trivy-action@master
        with:
          scan-type: 'fs'
          scan-ref: '.'
          severity: 'CRITICAL,HIGH'
          exit-code: '1'

  container-scan:
    runs-on: ubuntu-latest
    needs: [dependency-scan]
    steps:
      - uses: actions/checkout@v4
      - name: Build container
        run: docker build -t app:${{ github.sha }} .
      - name: Trivy image scan
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: 'app:${{ github.sha }}'
          severity: 'CRITICAL'
          exit-code: '1'

  infrastructure-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Checkov IaC scan
        uses: bridgecrewio/checkov-action@master
        with:
          directory: ./terraform
          framework: terraform
          soft_fail: false
Enter fullscreen mode Exit fullscreen mode

Why This Order Matters

Secret scanning runs first and independently. If there are hardcoded credentials, nothing else matters -- stop the pipeline immediately.

Dependency scanning runs before container scanning because if the dependency file has a critical CVE, building the container is wasted compute.

Infrastructure scanning runs independently because it does not depend on the application build.

Threshold Tuning

The most important decision is what severity breaks the build:

  • Secret detection: Any finding = build failure. Zero tolerance.
  • Dependency scanning: CRITICAL + HIGH with known exploits = build failure.
  • Container scanning: CRITICAL only = build failure. HIGH creates a ticket.
  • IaC scanning: Security misconfigurations = build failure. Best practice recommendations = warning.

Getting the thresholds wrong in either direction kills adoption. Too strict, and developers route around the pipeline. Too lenient, and the pipeline provides false confidence.

Full DevSecOps guide: DevSecOps Pipeline Tutorial

Top comments (0)