Shifting Left: Automating DevSecOps in Your CI/CD Pipeline

Automating DevSecOps in Your CI/CD Pipeline

In the era of continuous delivery, speed is paramount. But what about security? The traditional approach of security “gatekeepers” at the end of the release cycle is no longer sustainable. It introduces bottlenecks, increases the cost of fixing vulnerabilities, and leaves organizations exposed to critical risks.

Welcome to DevSecOps, a cultural and technical shift that embeds security into every stage of the software development lifecycle (SDLC). In mid-2025, the mantra is clear: Shift Left. This means automating security checks as early as possible in your CI/CD pipeline, empowering developers to build secure code from the start.

This post will guide you through practical ways to automate DevSecOps in your CI/CD pipeline, providing actionable code examples using popular open-source tools. By the end, you’ll see how to integrate security seamlessly, making it a natural part of your development workflow, not an afterthought.

1. The Imperative to Shift Left

Why is “shifting left” so critical?

  • Cost Efficiency: Finding and fixing a bug or vulnerability in the requirements or coding phase is significantly cheaper than in production.
  • Faster Feedback: Developers get immediate feedback on security issues, allowing for quicker remediation and learning.
  • Shared Responsibility: Security becomes everyone’s job, fostering a stronger security culture.
  • Reduced Risk: Proactive detection minimizes the attack surface and prevents vulnerable code from reaching production.

Automation is the backbone of effective shift-left. Let’s look at how to implement it.

2. Secrets Detection in Code (Pre-Commit/CI)

Accidentally committing API keys, database credentials, or private keys to source control is a common and dangerous mistake. Automated secrets scanning prevents this.

Tool: GitLeaks (or trufflehog) is an excellent open-source choice.

Integrating GitLeaks into GitHub Actions

You can run GitLeaks as part of your CI pipeline to scan every push or pull request.

.github/workflows/secrets-scan.yaml:

YAML

# .github/workflows/secrets-scan.yaml
name: Secrets Scan
on: [push, pull_request]

jobs:
  gitleaks:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0 # Fetch all history for a full scan

      - name: Run Gitleaks
        uses: zricethez/gitleaks-action@v3 # Use the official Gitleaks action
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Required for some Gitleaks features
          # Optional: GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }} # If using enterprise features
        with:
          config_path: .gitleaks.toml # Path to your custom Gitleaks config if needed
          # Arguments like '--verbose', '--redact' can be added here
          # For stricter checks, remove allow_fail: true
          # allow_fail: true # Uncomment in development to allow pipeline to pass on first finds

gitleaks.toml (example for custom rules or ignoring specific paths):

Ini, TOML

# .gitleaks.toml
[extend]
# You can extend built-in rules or define your own
# source = "https://raw.githubusercontent.com/zricethez/gitleaks/master/config/gitleaks.toml"

[[rules]]
  description = "Custom API Key"
  regex = '''api_key_[a-zA-Z0-9]{32}''' # Example custom regex for an API key pattern
  tags = ["api", "custom"]

[[whitelist]]
  description = "Ignore specific paths"
  regex = '''^(vendor/|node_modules/|testdata/)''' # Ignore common vendor/test dirs

This workflow will automatically scan your codebase for secrets on every code change, failing the build if any are found (unless allow_fail is set to true for testing).

3. Static Application Security Testing (SAST)

SAST tools analyze your source code for common vulnerabilities (e.g., SQL injection, XSS, insecure deserialization) without executing the application.

Tool: Semgrep (open-source, highly configurable) or SonarQube Community Edition.

Integrating Semgrep into GitLab CI/CD

YAML

# .gitlab-ci.yml
stages:
  - build
  - security-scan
  - deploy

build_app:
  stage: build
  script:
    - echo "Building application..."
    # Your application build commands here
    - sleep 5 # Simulate build time
  artifacts:
    paths:
      - . # If build generates artifacts needed for later stages

semgrep_sast_scan:
  stage: security-scan
  image: returntocorp/semgrep # Official Semgrep Docker image
  script:
    - echo "Running Semgrep SAST scan..."
    - semgrep ci --metrics=off --json --output=semgrep.json --error # Run CI mode, output JSON, exit with error on findings
  artifacts:
    reports:
      semgrep: semgrep.json # GitLab SAST report format
    paths:
      - semgrep.json # Save the raw output
  allow_failure: true # Set to false in production for mandatory checks

This integrates a basic Semgrep scan. For more advanced use, you’d specify custom rulesets (semgrep --config="p/python", "p/ci-best-practices") and parse results. GitLab CI can even display findings directly in merge requests.

4. Software Composition Analysis (SCA)

SCA tools identify known vulnerabilities in your third-party libraries and dependencies. Most applications rely heavily on open-source components, making SCA crucial.

Tool: Trivy (all-in-one, also does container/IaC scanning) or OWASP Dependency-Check.

Integrating Trivy for Dependency Scanning (Node.js example)

YAML

# .github/workflows/dependency-scan.yaml
name: Dependency Scan
on: [push, pull_request]

jobs:
  trivy_sca:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Run Trivy FS (file system) scan for dependencies
        uses: aquasecurity/trivy-action@master
        with:
          scan-type: 'fs' # Scan file system for dependencies
          # Supported types: 'fs', 'image', 'repo', 'cluster'
          format: 'sarif' # Output in SARIF format for GitHub Security tab
          output: 'trivy-results.sarif'
          severity: 'CRITICAL,HIGH' # Only report critical and high severity issues
          ignore-unfixed: true # Only report fixable vulnerabilities
          # Optional: Add --scanners "vuln,config,secret" for a more comprehensive scan

      - name: Upload Trivy results to GitHub Security tab
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: 'trivy-results.sarif'
          category: 'trivy-dependency-scan' # A category for the results
        if: always() # Upload even if previous step fails

This workflow uses Trivy to scan your project’s dependencies for known CVEs and uploads the results directly to GitHub’s Security tab, providing a centralized view of your vulnerabilities.

5. Container Image Scanning

Before deploying a Docker image, scan it for OS vulnerabilities, misconfigurations, and embedded secrets.

Tool: Trivy (again, versatile!) or Clair.

Integrating Trivy for Container Image Scanning

Building on the previous example, after your Docker image is built:

YAML

# .github/workflows/container-image-scan.yaml
name: Container Image Scan
on:
  push:
    branches:
      - main
    # Or on tag creation, after image build and push
  workflow_dispatch: # Allows manual trigger

jobs:
  build_and_scan:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Log in to Docker Hub (or other registry)
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Build and push Docker image
        uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: your-docker-repo/your-app:latest # Replace with your image name
          cache-from: type=gha # Optional caching

      - name: Run Trivy image scan
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: 'your-docker-repo/your-app:latest' # The image we just built
          format: 'table' # Or 'sarif' for GitHub Security
          output: 'trivy-image-results.txt'
          severity: 'CRITICAL,HIGH'
          ignore-unfixed: true
          # For stricter checks, remove allow-failure
          allow-failure: false # Make this pipeline fail if critical/high vulns are found

      - name: Upload Trivy image scan results (optional)
        uses: actions/upload-artifact@v4
        with:
          name: trivy-image-scan-results
          path: trivy-image-results.txt

This workflow ensures that only relatively “clean” images proceed down your pipeline, catching vulnerabilities before deployment.

6. Infrastructure as Code (IaC) Security Scanning

Misconfigurations in your IaC (Terraform, Kubernetes YAML, CloudFormation) can create security holes before anything is even deployed.

Tool: Checkov (open-source) or Terrascan.

Integrating Checkov for IaC Scanning (Terraform example)

YAML

# .github/workflows/iac-scan.yaml
name: IaC Security Scan
on: [push, pull_request]

jobs:
  checkov_scan:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Install Checkov
        run: pip install checkov

      - name: Run Checkov IaC scan on Terraform
        run: |
          checkov -d . --framework terraform --output cli --output-file-path checkov-results.txt
        env:
          BC_SKIP_DEBUG_REPORT: true # Suppress debug report to reduce log noise

Note on Checkov and Prisma Cloud: While Checkov is a powerful open-source tool for IaC scanning, it was originally developed by Bridgecrew, which was acquired by Palo Alto Networks. Its commercial integration is now part of Prisma Cloud. For advanced features like centralized reporting across multiple repositories or deep integrations with commercial cloud security platforms, you would explore Prisma Cloud and its associated API keys/access methods. For standalone CI/CD scanning, Checkov works perfectly as shown above.

This setup quickly scans your Terraform files for common security misconfigurations (e.g., S3 buckets without encryption, open security groups, public IPs).

Conclusion

Automating DevSecOps in your CI/CD pipeline is no longer optional; it’s a fundamental requirement for secure and agile software delivery in 2025. By embedding secrets detection, SAST, SCA, container scanning, and IaC security checks directly into your workflows, you empower your developers, reduce security debt, and build a more resilient software supply chain.

Start with one or two tools, integrate them into a pilot project, and gradually expand your DevSecOps automation. The initial investment pays dividends in reduced risks, faster remediation, and ultimately, a more secure product.

What DevSecOps challenges are you currently tackling in your CI/CD? Share your insights and preferred tools!

You Might Also Like

Want to Listen to This Guide While Working?

Try Speechify — the AI voice reader that helps DevOps engineers consume technical documentation while working in the terminal.