Cloud Security

DevSecOps Pipeline: How to Build Security into CI/CD

Learn how to integrate security into your CI/CD pipeline. This guide covers SAST, DAST, SCA, container scanning, and security automation for DevSecOps teams.

By InventiveHQ Team

DevSecOps is the practice of building automated security testing into every stage of a CI/CD pipeline so vulnerabilities are caught by the pipeline itself rather than by a human audit or an attacker. In concrete terms it means running secret scanning and static analysis (SAST) on every commit, dependency scanning (SCA) and container scanning at build time, infrastructure-as-code checks before deploy, dynamic testing (DAST) against staging, and continuous monitoring in production — each check gating the next so insecure code cannot progress. The core principle is "shift left": find flaws when they are cheap, because a defect caught in code review costs a fraction of the same defect found in production.

That's the summary an AI gives you. What it can't show you is the sequence — which scan runs where, what it gates, and what a real, copy-pasteable pipeline looks like end to end. The animated flow below maps every scan to its pipeline stage, and the rest of this guide is a working GitHub Actions pipeline you can lift, stage by stage.


What Is DevSecOps?

DevSecOps integrates security practices into the DevOps workflow:

  • Shift left - Find issues earlier in the development cycle
  • Automate - Security checks run automatically, not manually
  • Continuous - Every commit and deployment gets scanned
  • Collaborative - Security is everyone's responsibility, not just the security team

The goal: deploy faster AND more securely by catching issues before they reach production.


The DevSecOps Pipeline

A mature DevSecOps pipeline includes security at every stage. The diagram below traces a commit through all six gates — a moving pulse follows the code from the developer's laptop to production, and each stage lists the scans that gate it:

The six-stage DevSecOps pipeline A commit flows left to right through Code, Build, Package, Deploy, Test, and Monitor stages. Each stage runs specific security scans that must pass before the code advances. Security at every stage of CI/CD 1 Code pre-commit Secret scan SAST Linting GATE 2 Build on push / PR SCA (deps) CodeQL SBOM gen GATE 3 Package container Image scan Trivy / Grype Cosign sign GATE 4 Deploy IaC / config Checkov KICS K8s policy GATE 5 Test staging DAST (ZAP) API tests Nuclei GATE 6 Monitor production Runtime scan SIEM / alerts CSPM LOOP

Cost to fix rises left to right — the same flaw is ~100x more expensive to remediate once it reaches Monitor.


Which Scan Finds What

The single most common DevSecOps mistake is treating these scan types as interchangeable. They find different classes of bug, at different points, and none of them substitutes for another. Use this to decide what to add and where it runs:

ScanWhat it inspectsFindsRuns atSpeedAdd it when
Secret scanningDiffs & git historyLeaked keys, tokens, passwordsPre-commit + pushSecondsFirst — highest signal, zero ambiguity
SCAThird-party dependenciesKnown CVEs in libraries you importedBuildSeconds–minsFirst — most breaches start here
SASTYour own source codeInjection, XSS, unsafe crypto in code you wroteBuild (per commit)MinsAfter secrets + SCA are stable
Container scanImage layers & OS packagesVulnerable base images, OS CVEsPackageMinsOnce you ship containers
IaC scanTerraform/K8s/CloudFormationMisconfig: open buckets, 0.0.0.0/0, no encryptionDeploySecondsOnce infra lives in code
DASTThe running applicationRuntime/OWASP Top 10, auth & config flawsTest (staging)10–30 minOnce you have a stable staging URL
Runtime / CSPMLive productionDrift, exposed services, active exploitationMonitorContinuousOnce you're in production

The rule of thumb: SAST finds bugs you wrote, SCA finds bugs you imported, DAST finds bugs that only appear when the app is live. You need all three, plus the infrastructure and runtime layers around them.


Stage 1: Secure Code (Pre-Commit)

Catch issues before code enters the repository.

Pre-Commit Hooks

Run security checks locally before commits:

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.5.0
    hooks:
      - id: detect-private-key
      - id: detect-aws-credentials

  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.18.0
    hooks:
      - id: gitleaks

  - repo: https://github.com/PyCQA/bandit
    rev: 1.7.6
    hooks:
      - id: bandit
        args: ["-r", "src/"]

  - repo: https://github.com/aquasecurity/tfsec
    rev: v1.28.4
    hooks:
      - id: tfsec
Advertisement

Secret Scanning

Prevent credentials from entering version control:

Gitleaks configuration:

# .gitleaks.toml
title = "Custom Gitleaks Config"

[[rules]]
id = "api-key"
description = "API Key"
regex = '''(?i)(api[_-]?key|apikey)['":\s]*[=:]\s*['"]?([a-z0-9]{32,})['"]?'''
tags = ["api", "key"]

[[rules]]
id = "aws-access-key"
description = "AWS Access Key"
regex = '''AKIA[0-9A-Z]{16}'''
tags = ["aws", "key"]

Stage 2: Static Analysis (Build)

Analyze code without executing it.

SAST (Static Application Security Testing)

Scan source code for vulnerabilities:

GitHub Actions example:

name: Security Scan

on: [push, pull_request]

jobs:
  sast:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # Semgrep for multi-language SAST
      - name: Semgrep Scan
        uses: returntocorp/semgrep-action@v1
        with:
          config: >-
            p/security-audit
            p/owasp-top-ten
            p/cwe-top-25

      # CodeQL for deeper analysis
      - name: Initialize CodeQL
        uses: github/codeql-action/init@v2
        with:
          languages: javascript, python

      - name: Perform CodeQL Analysis
        uses: github/codeql-action/analyze@v2

Popular SAST tools:

ToolLanguagesBest For
Semgrep30+ languagesSpeed, custom rules
CodeQL10+ languagesDeep analysis, GitHub integration
SonarQube25+ languagesQuality + security
Snyk Code10+ languagesDeveloper experience
Checkmarx25+ languagesEnterprise, compliance

SCA (Software Composition Analysis)

Scan dependencies for known vulnerabilities:

- name: Dependency Check
  uses: dependency-check/Dependency-Check_Action@main
  with:
    project: 'MyApp'
    path: '.'
    format: 'SARIF'
    args: >-
      --failOnCVSS 7
      --enableRetired

- name: Snyk Dependencies
  uses: snyk/actions/node@master
  with:
    args: --severity-threshold=high
  env:
    SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}

What SCA finds:

  • Known CVEs in dependencies
  • Outdated packages
  • License compliance issues
  • Transitive dependency risks

Stage 3: Container Security (Package)

Secure container images before they ship.

Image Scanning

container-scan:
  runs-on: ubuntu-latest
  steps:
    - name: Build Image
      run: docker build -t myapp:${{ github.sha }} .

    - name: Trivy Scan
      uses: aquasecurity/trivy-action@master
      with:
        image-ref: 'myapp:${{ github.sha }}'
        format: 'sarif'
        severity: 'CRITICAL,HIGH'
        exit-code: '1'

    - name: Grype Scan
      uses: anchore/scan-action@v3
      with:
        image: 'myapp:${{ github.sha }}'
        fail-build: true
        severity-cutoff: high

Image Signing

Ensure only trusted images deploy:

- name: Sign Image
  run: |
    cosign sign --key env://COSIGN_KEY \
      ${{ env.REGISTRY }}/myapp:${{ github.sha }}
  env:
    COSIGN_KEY: ${{ secrets.COSIGN_PRIVATE_KEY }}

Stage 4: Infrastructure Security (Deploy)

Scan infrastructure configurations before deployment.

IaC Scanning

infrastructure-scan:
  runs-on: ubuntu-latest
  steps:
    - name: Checkov IaC Scan
      uses: bridgecrewio/checkov-action@master
      with:
        directory: terraform/
        framework: terraform
        output_format: sarif

    - name: KICS Scan
      uses: checkmarx/kics-github-action@v1.7.0
      with:
        path: ./
        fail_on: high
        output_formats: 'sarif'

Kubernetes Manifest Scanning

- name: Kubesec Scan
  uses: controlplaneio/kubesec-action@v0.0.2
  with:
    input: k8s/deployment.yaml

- name: Polaris Audit
  run: |
    polaris audit --audit-path ./k8s/ \
      --format json \
      --set-exit-code-on-danger

Stage 5: Dynamic Testing (Test)

Test running applications for vulnerabilities.

DAST (Dynamic Application Security Testing)

Scan running applications for OWASP Top 10 issues:

dast:
  runs-on: ubuntu-latest
  steps:
    - name: Start Application
      run: docker-compose up -d

    - name: Wait for App
      run: sleep 30

    - name: ZAP Baseline Scan
      uses: zaproxy/action-baseline@v0.10.0
      with:
        target: 'http://localhost:8080'
        rules_file_name: '.zap/rules.tsv'

    - name: ZAP Full Scan
      uses: zaproxy/action-full-scan@v0.8.0
      with:
        target: 'http://localhost:8080'

API Security Testing

- name: API Security Test
  run: |
    # Postman/Newman for API tests
    newman run api-security-tests.json \
      --environment staging.json \
      --reporters cli,junit

    # OWASP Juice Shop example
    nuclei -u http://localhost:8080 \
      -t api/ \
      -severity critical,high

Stage 6: Runtime Security (Monitor)

Continuous monitoring after deployment.

Security Monitoring Integration

# Send findings to SIEM
- name: Export to SIEM
  run: |
    # Convert SARIF to your SIEM format
    cat results.sarif | jq '.runs[].results[]' | \
    while read finding; do
      curl -X POST ${{ secrets.SIEM_WEBHOOK }} \
        -H "Content-Type: application/json" \
        -d "$finding"
    done

Continuous Scanning

Schedule regular scans of deployed infrastructure:

name: Scheduled Security Scan

on:
  schedule:
    - cron: '0 2 * * *'  # Daily at 2 AM

jobs:
  scan-production:
    runs-on: ubuntu-latest
    steps:
      - name: Scan Production Images
        run: |
          trivy image --severity HIGH,CRITICAL \
            ${{ secrets.REGISTRY }}/myapp:production

      - name: Cloud Security Posture
        run: |
          prowler aws --severity high critical \
            --output-formats json

Sample Complete Pipeline

name: DevSecOps Pipeline

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  # Stage 1: Secret Scanning
  secrets:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - name: Gitleaks
        uses: gitleaks/gitleaks-action@v2

  # Stage 2: SAST
  sast:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Semgrep
        uses: returntocorp/semgrep-action@v1
        with:
          config: p/security-audit

  # Stage 3: SCA
  sca:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Snyk
        uses: snyk/actions/node@master
        with:
          args: --severity-threshold=high
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}

  # Stage 4: Container Scan
  container:
    needs: [secrets, sast, sca]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build
        run: docker build -t myapp:${{ github.sha }} .
      - name: Trivy
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: 'myapp:${{ github.sha }}'
          exit-code: '1'
          severity: 'CRITICAL,HIGH'

  # Stage 5: IaC Scan
  iac:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Checkov
        uses: bridgecrewio/checkov-action@master
        with:
          directory: terraform/

  # Stage 6: Deploy (only if all scans pass)
  deploy:
    needs: [container, iac]
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - name: Deploy to Production
        run: echo "Deploying secure code..."

Metrics to Track

MetricTarget
Mean Time to Remediate (MTTR)< 7 days for critical
Vulnerabilities blocked pre-production> 90%
False positive rate< 10%
Pipeline pass rate> 95%
Security scan coverage100% of deployments

Frequently Asked Questions

How do I handle false positives?

False positives are inevitable. Create suppression files for known false positives, regularly review and update them, and track false positive rates as a metric. Most tools support inline comments to suppress specific findings.

Will security scans slow down my pipeline?

Well-designed security scans add 5-15 minutes to pipelines. Run scans in parallel, use incremental scanning where possible, and cache results. The time is worth it compared to fixing production vulnerabilities.

Should security block deployments?

Yes, for critical and high severity findings. Use a tiered approach: block critical issues, warn on medium issues, and log low issues for later review. Gradually increase strictness as your team matures.

How do I get developer buy-in for DevSecOps?

Make security frictionless. Provide clear remediation guidance, integrate findings into existing tools (IDE plugins, PR comments), and celebrate security wins. Developers adopt security when it's helpful, not punitive.

What's the most important security scan to add first?

Start with secret scanning and SCA—they have the highest signal-to-noise ratio and catch issues developers commonly miss. Add SAST next, then container scanning, then IaC scanning.


DevSecOps Rollout Checklist

Add these in order. Each row is a gate you can turn from "warn" to "block" once the false-positive rate settles. Do not try to enable everything at once — that is how teams end up disabling the whole pipeline.

  • Week 1 — Secrets: Gitleaks pre-commit hook + repo-side secret scanning. Rotate anything it finds.
  • Week 1 — Dependencies (SCA): Enable Dependabot/Snyk; fail build on high-severity CVEs.
  • Week 2 — SAST: Add Semgrep with p/security-audit; run diff-only on PRs to stay fast.
  • Week 3 — SBOM: Generate an SBOM (Syft/CycloneDX) on every build and store it as an artifact.
  • Week 3 — Container scan: Trivy or Grype on the built image; block CRITICAL/HIGH.
  • Week 4 — Image signing: Sign images with Cosign; verify signatures at deploy.
  • Week 4 — IaC scan: Checkov/KICS over Terraform and Kubernetes manifests.
  • Week 5 — DAST: ZAP baseline against staging on merge; full scan nightly.
  • Week 6 — Runtime: Ship findings to your SIEM; schedule daily production image + CSPM scans.
  • Ongoing — Gate tuning: Track false-positive rate; ratchet gates from warn to block as they stabilize.

Take Action

  1. Add secret scanning - Prevent credentials from entering your repository
  2. Enable dependency scanning - Catch known CVEs in your dependencies
  3. Scan container images - Check for vulnerabilities before deployment
  4. Implement IaC scanning - Catch misconfigurations in infrastructure code
  5. Track metrics - Measure MTTR, blocked vulnerabilities, and coverage

For more cloud security guidance, see our comprehensive guide: 30 Cloud Security Tips for 2026.


Need Help Implementing DevSecOps?

Our team helps organizations integrate security into CI/CD pipelines without slowing down deployments:

Frequently Asked Questions

What is the difference between SAST, DAST, and SCA?

SAST (Static Application Security Testing) scans your own source code without running it, catching flaws like SQL injection and hardcoded secrets early. DAST (Dynamic Application Security Testing) attacks a running application from the outside, finding runtime and configuration issues SAST cannot see. SCA (Software Composition Analysis) scans your third-party dependencies for known CVEs. They are complementary, not interchangeable: SAST finds bugs you wrote, SCA finds bugs you imported, and DAST finds bugs that only appear when the app is live. A mature pipeline runs all three.

What order do security scans run in a DevSecOps pipeline?

Fastest and cheapest first. Pre-commit hooks and secret scanning run on the developer's machine, then SAST and SCA run on every push (seconds to a couple of minutes), then container and IaC scanning run at build time, then DAST runs against a deployed staging build, and finally runtime monitoring watches production. This "shift left" ordering surfaces the majority of issues before an expensive DAST run or a production deploy ever happens.

Should security scans block a deployment?

Yes for critical and high-severity findings, and generally no for low-severity noise. Use a tiered gate: fail the build on critical and high issues, warn on medium, and log low issues for later triage. Start lenient while your team tunes out false positives, then ratchet the gate stricter over time. Blocking everything on day one is the fastest way to get developers to disable the scans entirely.

How much time do security scans add to a CI/CD pipeline?

Well-designed scans add roughly 5-15 minutes total. SAST and SCA are the slowest of the fast checks; DAST is the outlier and can take 10-30 minutes for a full scan. Keep the pipeline fast by running scan jobs in parallel, using incremental or diff-only scanning on pull requests, caching dependency databases, and reserving full DAST for nightly or pre-release runs rather than every commit.

What is the first security scan I should add?

Secret scanning and SCA. Both have the highest signal-to-noise ratio: leaked credentials and known-vulnerable dependencies are unambiguous, common, and easy to remediate. Gitleaks or GitHub secret scanning plus a dependency scanner like Snyk, Dependabot, or OWASP Dependency-Check will catch the issues that cause the most real-world breaches with the least developer friction. Add SAST next, then container and IaC scanning.

How do I handle false positives in security scanners?

Treat false positives as a metric you actively drive down, not background noise. Use each tool's suppression mechanism (inline comments, .semgrepignore, baseline files, or a triaged suppression list), require a short justification for every suppression, and review the suppression file periodically so it does not hide real regressions. Track your false-positive rate over time; a rate above 10-15 percent usually means the ruleset needs tuning to your codebase.

What is shift-left security?

Shift-left security means moving security testing earlier in the development lifecycle, toward the developer's keyboard and away from a final pre-release audit. Instead of a security team reviewing a finished build, checks run in the IDE, in pre-commit hooks, and on every pull request. The payoff is cost: a vulnerability caught in a code review is far cheaper to fix than the same flaw found in production after it has shipped.

Is DevSecOps only for large enterprises?

No. The core building blocks (secret scanning, dependency scanning, and SAST) are free, open source, and installable in a GitHub Actions or GitLab CI file in an afternoon. A two-person team gets most of the value from Gitleaks plus Dependabot plus Semgrep with zero licensing cost. Enterprise tooling adds centralized reporting, compliance evidence, and support, but the security wins are available at any scale.

DevSecOpsCI/CD SecuritySASTDASTSCAApplication SecurityShift Left Security