DevSecOps embeds security into every stage of the software development lifecycle. Rather than running security assessments at the end of a release cycle, DevSecOps shifts security left into development and CI/CD pipelines. This article covers how to integrate SAST, DAST, dependency scanning, container scanning, and policy-as-code into your pipelines.


Shift-Left Security


The shift-left principle moves security testing earlier in the development process. Finding and fixing a vulnerability during development costs 10 times less than fixing it in production, and 100 times less than fixing it after a breach.


Security Gates in the Pipeline


A mature DevSecOps pipeline has security gates at every stage:



Code Commit -> SAST -> Dependency Scan -> Build -> Container Scan -> 

Integration Test -> DAST -> Staging -> Policy Check -> Production


Each gate can pass, fail with a warning, or fail and block the pipeline. The severity determines the action: critical and high findings block the pipeline, while medium and low findings create tickets for the development team.


Static Application Security Testing (SAST)


SAST analyzes source code without executing it. It identifies vulnerabilities like SQL injection, cross-site scripting (XSS), buffer overflows, and insecure cryptographic usage.


Popular SAST Tools


  • **Semgrep**: Open-source, fast, and supports custom rules. Works with most programming languages.
  • **SonarQube**: Static analysis with quality gates and technical debt tracking.
  • **CodeQL**: GitHub's semantic code analysis engine. Query-based vulnerability detection.
  • **Checkmarx / Fortify**: Commercial SAST tools with extensive rule sets.

  • Pipeline Integration


    
    # GitHub Actions: SAST with Semgrep
    
    name: SAST Scan
    
    on:
    
      pull_request:
    
        branches: [main]
    
    
    
    jobs:
    
      semgrep:
    
        runs-on: ubuntu-latest
    
        steps:
    
          - uses: actions/checkout@v4
    
          - uses: semgrep/semgrep-action@v1
    
            with:
    
              config: p/default
    
              audit_on: push
    
          - name: Check for blocking findings
    
            run: |
    
              if [ "${{ steps.semgrep.outputs.results }}" != "" ]; then
    
                echo "SAST found vulnerabilities. Fix before merging."
    
                exit 1
    
              fi
    
    

    SAST Best Practices


  • Run SAST on every pull request, not just on push to main.
  • Use incremental scanning for faster feedback on large codebases.
  • Tune rules to reduce false positives. Block only high-confidence findings.
  • Create custom rules for your application's specific security patterns.

  • Dependency Scanning


    Modern applications use dozens of open-source libraries. Each library introduces transitive dependencies with potential vulnerabilities.


    Software Bill of Materials (SBOM)


    An SBOM is a formal inventory of all software components in an application. Generate SBOMs in CycloneDX or SPDX format.


    
    # Generate SBOM with Syft
    
    syft packages . -o cyclonedx-json > sbom.json
    
    
    
    # Scan SBOM for vulnerabilities with Grype
    
    grype sbom:./sbom.json
    
    

    Dependency Scanning Tools


  • **Dependabot**: GitHub's built-in dependency scanning and automated pull requests for patches.
  • **Renovate**: Open-source dependency update tool with extensive customization.
  • **Snyk**: Commercial vulnerability scanner with fix advice and license compliance.
  • **OWASP Dependency-Check**: Open-source scanner that identifies CVEs in dependencies.

  • 
    # Dependabot configuration
    
    version: 2
    
    updates:
    
      - package-ecosystem: "npm"
    
        directory: "/"
    
        schedule:
    
          interval: "weekly"
    
        open-pull-requests-limit: 10
    
        labels:
    
          - "dependencies"
    
          - "security"
    
    

    Dependency Scanning Policy


  • Block the pipeline on critical or high severity vulnerabilities in direct dependencies.
  • Flag transitive dependency vulnerabilities but only block if they are exploitable.
  • Require automated dependency updates within 7 days for critical, 30 days for high.
  • Monitor for license compliance alongside vulnerability scanning.

  • Dynamic Application Security Testing (DAST)


    DAST tests the running application from the outside, simulating real-world attack patterns. It discovers vulnerabilities that SAST misses, such as authentication bypass, session management flaws, and business logic errors.


    DAST Tools


  • **OWASP ZAP**: Open-source web application scanner with automated and manual modes.
  • **Burp Suite**: Commercial web security testing platform with advanced scanning.
  • **Arachni**: Open-source web application security scanner framework.

  • Pipeline Integration


    
    # DAST with OWASP ZAP in CI/CD
    
    services:
    
      zap:
    
        image: ghcr.io/zaproxy/zaproxy:stable
    
        options: --user root
    
    
    
    steps:
    
      - name: Run ZAP Scan
    
        run: |
    
          docker run -v $(pwd):/zap/wrk:rw \
    
            ghcr.io/zaproxy/zaproxy:stable \
    
            zap-full-scan.py \
    
            -t https://staging.example.com \
    
            -r zap_report.html \
    
            -z "-config spider.maxDuration=10"
    
      - name: Check ZAP Results
    
        run: |
    
          if grep -q "High" zap_report.html; then
    
            echo "DAST found High severity issues"
    
            exit 1
    
          fi
    
    

    DAST Best Practices


  • Run DAST against staging or review environments, not production.
  • Authenticate DAST scanners to test authenticated functionality.
  • Use baseline scans for smoke testing and full scans for release candidates.
  • Integrate with Jira or ticketing for automatic issue creation.

  • Container Scanning


    Container images bundle applications with their runtime dependencies. Vulnerabilities in base images or installed packages become part of the container.


    Scanning Pipeline Integration


    
    # Dockerfile with security best practices
    
    FROM alpine:3.19 AS builder
    
    RUN apk add --no-cache build-base
    
    
    
    FROM alpine:3.19
    
    RUN apk add --no-cache ca-certificates && \
    
        addgroup -S app && adduser -S app -G app
    
    COPY --from=builder /app/bin/server /app/server
    
    USER app
    
    EXPOSE 8080
    
    

    
    # Container scanning with Trivy in CI/CD
    
    jobs:
    
      scan:
    
        runs-on: ubuntu-latest
    
        steps:
    
          - uses: actions/checkout@v4
    
          - name: Build image
    
            run: docker build -t myapp:${{ github.sha }} .
    
          - name: Scan with Trivy
    
            uses: aquasecurity/trivy-action@master
    
            with:
    
              image-ref: myapp:${{ github.sha }}
    
              format: sarif
    
              output: trivy-results.sarif
    
              severity: CRITICAL,HIGH
    
          - name: Upload results
    
            uses: github/codeql-action/upload-sarif@v3
    
            with:
    
              sarif_file: trivy-results.sarif
    
    

    Container Security Practices


  • Use minimal base images (Alpine, distroless) to reduce attack surface.
  • Scan images before pushing to the registry.
  • Enforce signed images with Cosign.
  • Enable granular runtime security with seccomp, AppArmor, or SELinux policies.

  • Policy-as-Code


    Policy-as-code defines security and compliance rules as executable code. Policies are versioned, reviewed, and enforced automatically in the pipeline.


    Open Policy Agent (OPA) and Rego


    OPA enforces policies across the software lifecycle. Rego is OPA's policy language.


    
    # Rego policy: Require encryption at rest
    
    package kubernetes.storage
    
    
    
    deny[msg] {
    
      volume := input.volumes[_]
    
      volume.persistentVolumeClaim
    
      not volume.encrypted
    
      msg := sprintf("Volume %v must have encryption enabled", [volume.name])
    
    }
    
    

    Policy Gates in the Pipeline


    
    # Conftest: Policy enforcement for Kubernetes manifests
    
    steps:
    
      - name: Check Kubernetes policies
    
        run: |
    
          conftest test deployment.yaml \
    
            --policy policies/ \
    
            --namespace kubernetes
    
      - name: Check Terraform policies
    
        run: |
    
          conftest test main.tf \
    
            --policy policies/terraform/
    
    

    Common Policy Rules


  • Containers must not run as root.
  • All ingress must have TLS enabled.
  • S3 buckets must block public access.
  • Database instances must have encryption at rest.
  • IAM roles must have resource-level constraints.

  • Building a DevSecOps Culture


    Tools alone do not make DevSecOps successful. The human elements matter more.


  • **Developer empowerment**: Give developers access to security scan results and fix guidance. Do not use security as a gate without providing remediation support.
  • **Security champions**: Train security champions in each development team. They bridge the gap between security and engineering.
  • **Friction reduction**: Optimize scan times. A 30-minute SAST scan encourages skipping. A 2-minute scan integrates naturally into the workflow.
  • **Blameless culture**: When security scans find issues, the process worked correctly. Celebrate catching issues early rather than blaming developers.

  • Conclusion


    DevSecOps shifts security from a final gate to an integrated part of the development process. SAST catches code-level vulnerabilities, dependency scanning manages supply chain risk, DAST validates runtime behavior, container scanning secures artifacts, and policy-as-code enforces standards. Together, these practices make security a natural part of delivering software, not an obstacle to it.