
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.