Skip to content

DevSecOps Pipeline Integration — SAST, DAST, Dependency Scanning, and Security Gates

DodaTech Updated 2026-06-22 9 min read

In this tutorial, you'll learn about DevSecOps Pipeline Integration. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.

DevSecOps integrates Security Testing directly into the CI/CD pipeline — shifting left by running Static Analysis, dynamic scanning, dependency checks, and container analysis at every commit instead of waiting for a separate security review.

What You'll Learn

Why It Matters

Traditional Security Testing happens at the end of development — a penetration test before release that finds dozens of issues requiring emergency fixes. DevSecOps embeds automated security checks into every pipeline run. Vulnerabilities are caught minutes after they are introduced, when they cost the least to fix. The pipeline itself enforces security gates that block releases failing critical checks.

Real-World Use

Durga Antivirus Pro's CI/CD pipeline runs six security stages on every Pull Request: SAST with Semgrep for custom rule violations, dependency scanning with npm audit and Trivy, container image scanning for OS vulnerabilities, infrastructure scanning for Terraform misconfigurations, DAST against the staging environment, and license Compliance checks — all enforced through quality gates that block merging on high-severity findings.

flowchart LR
    A[Code Commit] --> B[SAST: Semgrep]
    A --> C[Dep Scan: npm audit]
    A --> D[IaC Scan: Checkov]
    B --> E[Build & Test]
    C --> E
    D --> E
    E --> F[Container Scan]
    F --> G[DAST: OWASP ZAP]
    G --> H{Security Gate}
    H -->|Pass| I[Deploy]
    H -->|Fail| J[Block & Notify]
    style H fill:#ff9800,color:#fff
    style J fill:#f44336,color:#fff
    style I fill:#4CAF50,color:#fff
â„šī¸ Info

Prerequisites: CI/CD pipeline concepts, basic Docker knowledge, familiarity with OWASP vulnerability classifications.

SAST — Static Application Security Testing

SAST analyzes source code for security vulnerabilities without executing the application. It catches issues like SQL Injection, cross-site scripting, hardcoded credentials, and insecure cryptographic usage.

# .github/workflows/sast.yml
name: SAST Scan

on:
  pull_request:
    branches: [main]

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

      - name: Run Semgrep
        uses: semgrep/semgrep-action@v1
        with:
          config: >-
            p/owasp-top-ten
            p/javascript
            p/nodejs
            p/security-audit
          auditOn: push
          publishDeployment: ${{ secrets.SEMGREP_APP_TOKEN }}

      - name: Check for blocking findings
        run: |
          if grep -q '"severity": "ERROR"' semgrep-results.json; then
            echo "Blocking security issues found!"
            exit 1
          fi

      - name: Comment results on PR
        uses: actions/github-script@v7
        if: github.event_name == 'pull_request'
        with:
          script: |
            const fs = require('fs');
            const results = JSON.parse(fs.readFileSync('semgrep-results.json'));
            // Format and post findings as PR comment

Expected behavior: Semgrep scans every changed file in the Pull Request against curated rule sets (OWASP Top 10, language-specific, custom rules). If any ERROR-severity findings exist, the pipeline fails and results are posted as a PR comment.

# Run Semgrep locally
semgrep --config=auto --severity=ERROR .

# Expected output:
# Scanning 142 files with 234 rules.
#   Found 3 findings:
#     src/auth.js:12
#       ❯ Severity: ERROR ❯ Rule: jwt-hardcoded-secret
#       Hardcoded JWT secret detected. Use environment variables.
#     src/db.js:45
#       ❯ Severity: ERROR ❯ Rule: sql-injection
#       User input concatenated into SQL query. Use parameterized queries.
# Ran 234 rules on 142 files: 3 findings.

DAST — Dynamic Application Security Testing

DAST tests the running application for vulnerabilities by sending malicious payloads and analyzing responses. It catches runtime issues SAST misses, such as misconfigured security headers and authentication bypasses.

# .github/workflows/dast.yml
name: DAST Scan

on:
  deployment_status:  # Runs when staging deployment completes
    types: [success]

jobs:
  zap-scan:
    runs-on: ubuntu-latest
    steps:
      - name: Run OWASP ZAP Scan
        uses: zaproxy/action-full-scan@v0.11.0
        with:
          target: ${{ github.event.deployment_status.target_url }}
          rules_file_name: .zap/rules.tsv
          cmd_options: '-a -j -J zap-report.json'
          issue_title: "DAST Scan Results"
          fail_action: true

      - name: Upload scan report
        uses: actions/upload-artifact@v4
        with:
          name: zap-report
          path: zap-report.json

Expected behavior: After the staging environment deploys successfully, DAST runs against the live URL. OWASP ZAP spiders the application, fuzzes endpoints, and checks for vulnerabilities. High-risk findings fail the workflow, preventing the same build from reaching production.

# Run OWASP ZAP in daemon mode
docker run -d --name zap -p 8080:8080 \
  -v $(pwd):/zap/wrk:rw \
  ghcr.io/zaproxy/zaproxy:stable \
  zap.sh -daemon -port 8080 -host 0.0.0.0

# Run an active scan
docker exec zap zap-cli active-scan \
  --recursive https://staging.myapp.com

# Expected output:
# Active Scan started against https://staging.myapp.com
# Spidering: 45 URLs discovered
# Active Scan: 1200+ requests sent
# Alerts found:
#   - Medium: Missing X-Frame-Options header
#   - Medium: Cookie without SameSite attribute
#   - Low: Server header disclosure

Dependency Scanning

Open-source dependencies are a primary attack vector. Dependency scanning checks every package against known vulnerability databases.

dep-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: npm audit
        run: |
          npm audit --audit-level=high --json > audit-results.json
          if jq -e '.metadata.vulnerabilities.high > 0 or
                    .metadata.vulnerabilities.critical > 0' \
                    audit-results.json > /dev/null; then
            echo "High or critical vulnerabilities found!"
            jq '.vulnerabilities | to_entries[] |
                {package: .key, severity: .value.severity,
                 title: .value.title, fix: .value.fixAvailable}' \
                audit-results.json
            exit 1
          fi

      - uses: actions/upload-artifact@v4
        with:
          name: npm-audit
          path: audit-results.json

Expected behavior: npm audit checks the project's dependency tree against the npm Advisory database. If any package has a high or critical vulnerability, the pipeline fails and displays remediation advice.

# Scan with Trivy for OS-level dependencies
trivy filesystem --severity CRITICAL,HIGH .

# Expected output:
# Total: 5 (CRITICAL: 2, HIGH: 3)
# +------------------+---------------------+----------+-----------+
# |    Library       |   Vulnerability     | Severity | Installed |
# +------------------+---------------------+----------+-----------+
# | lodash           | CVE-2024-XXXX       | CRITICAL | 4.17.20   |
# | express          | CVE-2024-YYYY       | HIGH     | 4.18.1    |
# | node-fetch       | CVE-2024-ZZZZ       | HIGH     | 2.6.7     |
# +------------------+---------------------+----------+-----------+

IaC Security Scanning

Infrastructure as Code configurations introduce security risks — open security groups, unencrypted storage, and public buckets are common misconfigurations.

iac-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Run Checkov
        id: checkov
        uses: bridgecrewio/checkov-action@master
        with:
          directory: terraform/
          framework: terraform
          output_format: cli
          soft_fail: false
          download_external_modules: true

      - name: Run tfsec
        run: |
          tfsec terraform/ --format sarif \
            --output-file tfsec-results.sarif

Expected behavior: Checkov and tfsec scan Terraform, CloudFormation, and Kubernetes manifests for misconfigurations against the CIS and Cloud Security benchmarks. Open security groups, unencrypted S3 buckets, and overly permissive IAM roles all trigger failures.

# Checkov flags this as a FAIL
resource "aws_security_group" "public_ssh" {
  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]  # FAIL: SSH open to world
  }
}

Expected output:

# checkov report for terraform/
# Passed checks: 45, Failed checks: 3
#
# FAIL: CKV_AWS_24 "Ensure no security groups allow ingress from 0.0.0.0:0 to port 22"
#   File: /terraform/security-groups.tf:4-10
#
# FAIL: CKV_AWS_23 "Ensure every security group rule has a description"

Security Gates

Security gates are quality thresholds that block the pipeline from proceeding when certain conditions are met.

# security-gate.sh
#!/bin/bash
set -e

HIGH_CRITICAL=$(jq '.runs[0].results |
  map(select(.level == "error")) | length' sarif-results.json)

if [ "$HIGH_CRITICAL" -gt 0 ]; then
  echo "BLOCKED: $HIGH_CRITICAL error-severity findings"
  exit 1
fi

echo "PASSED: Security gate cleared"

Expected behavior: The security gate script runs after all scans complete. If any ERROR-level findings exist, the script exits with code 1, causing the pipeline to fail. Only when all scans pass the gate does the pipeline proceed to deployment.

Container and Secret Scanning

container-scan:
    needs: build
    steps:
      - name: Scan Docker image
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: myapp:${{ github.sha }}
          severity: CRITICAL,HIGH
          exit-code: 1

  secret-scan:
    steps:
      - name: Scan for secrets
        uses: trufflesecurity/trufflehog@v3
        with:
          extra_args: --only-verified

Expected behavior: Container scanning blocks images with CRITICAL OS vulnerabilities. Secret scanning prevents API keys, tokens, and passwords from being committed.

Common Errors

  1. Running SAST only on main branch: Vulnerabilities found on main are already in the codebase. Run SAST on every Pull Request to catch issues before they merge.

  2. Not tuning scanner rules: Default rule sets produce many false positives. Teams ignore the results entirely. Invest time in customizing rules and suppressing known false positives.

  3. Skipping DAST because it is slow: DAST takes 20-60 minutes but catches runtime vulnerabilities no other scan finds. Run it as part of the staging deploy workflow rather than on every commit.

  4. Failing the build on every finding: Blocking the pipeline on LOW or INFO findings creates resentment against security. Gate only on HIGH and CRITICAL, and track lower-severity issues separately.

  5. Not scanning IaC configurations: Misconfigured infrastructure is one of the most common breach vectors. Terraform and Kubernetes manifests must be scanned alongside application code.

  6. Scanning dependencies without fixing them: Generating a list of vulnerabilities is useless without automated remediation. Configure Dependabot or Renovate to open fix PRs automatically.

Practice Questions

  1. What is the difference between SAST and DAST? Answer: SAST analyzes source code statically without running the application. DAST tests the running application by sending payloads and observing responses. SAST finds issues early; DAST finds runtime misconfigurations.

  2. Why should security gates be based only on HIGH and CRITICAL findings? Answer: Blocking on LOW and INFO findings creates too many pipeline failures, leading teams to ignore or disable security gates entirely. Focus on the most impactful vulnerabilities.

  3. How does dependency scanning work in a DevSecOps pipeline? Answer: The scanner compares every installed package version against vulnerability databases (npm Advisory, NVD, GitHub Advisory). If any version has a known CVE at or above the severity threshold, the pipeline blocks.

  4. Why should IaC scanning be included in the DevSecOps pipeline? Answer: IaC misconfigurations (open security groups, unencrypted storage, public S3 buckets) are common breach vectors. Automated IaC scanning catches these before they are deployed.

Challenge

Build a complete DevSecOps pipeline that runs SAST (Semgrep) on every Pull Request, dependency scanning (npm audit), IaC scanning (Checkov on Terraform), container scanning (Trivy), and a DAST scan (OWASP ZAP) after staging deployment. Implement a security gate that blocks the pipeline on HIGH and CRITICAL findings while posting WARNINGS as PR comments.

Mini Project

Create a GitHub Actions workflow with four security jobs: SAST using Semgrep with OWASP Top 10 rules, dependency scanning using npm audit, container scanning using Trivy with exit-code 1 on CRITICAL or HIGH, and IaC scanning using Checkov on a Terraform directory. Add a security gate job that aggregates results from all scanners and blocks deployment if any HIGH or CRITICAL findings exist. Configure Dependabot to auto-open PRs for vulnerable dependencies. Use a real-world web application repository to test the pipeline end-to-end.

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro