DevSecOps Complete Guide: Integrating Security into DevOps
📅 Published: June 2026
⏱️ Estimated Reading Time: 25 minutes
🏷️ Tags: DevSecOps, Security, CI/CD, SAST, DAST, Container Security
Introduction: What is DevSecOps?
DevSecOps means integrating security practices into the DevOps pipeline. Instead of treating security as a final gate before production, security is built into every stage of development and deployment.
Think of traditional security as a security guard at the building entrance. DevSecOps is like having security cameras, access badges, and alarms throughout the entire building.
The problem with traditional security:
Security testing happens at the end of development
Fixing issues is expensive and time-consuming
Security teams are seen as blockers
Developers lack security training
How DevSecOps solves this:
Security testing runs automatically in CI/CD
Issues are found early when they are cheap to fix
Security is everyone's responsibility
Developers get immediate feedback
This guide covers the complete DevSecOps pipeline, from code commit to production deployment.
Part 1: The DevSecOps Pipeline
Code → Commit → SAST → SCA → Build → Image Scan → Deploy → DAST → Runtime Security
| Stage | Security Practice | Tool Examples |
|---|---|---|
| Code | IDE security plugins | Snyk IDE, Semgrep |
| Commit | Pre-commit hooks, secret scanning | detect-secrets, truffleHog |
| CI | SAST (Static Analysis) | SonarQube, Checkmarx |
| CI | SCA (Software Composition Analysis) | Snyk, OWASP Dependency-Check |
| Build | Container image scanning | Trivy, Grype, Clair |
| Deploy | Infrastructure scanning | Checkov, tfsec |
| Staging | DAST (Dynamic Analysis) | OWASP ZAP, Burp Suite |
| Production | Runtime security | Falco, AppArmor, SELinux |
Part 2: Pre-Commit Security (Developer Workstation)
Secret Scanning with detect-secrets
Prevent secrets from ever entering Git history:
# Install detect-secrets pip install detect-secrets # Create baseline (scan existing code) detect-secrets scan > .secrets.baseline # Pre-commit hook cat > .git/hooks/pre-commit << 'EOF' #!/bin/bash detect-secrets-hook --baseline .secrets.baseline $(git diff --cached --name-only) EOF chmod +x .git/hooks/pre-commit
Git Hooks for Security
# pre-commit hook for AWS keys cat > .git/hooks/pre-commit << 'EOF' #!/bin/bash # Check for AWS keys if git diff --cached | grep -qE "AKIA[0-9A-Z]{16}"; then echo "❌ AWS Access Key detected in commit!" exit 1 fi # Check for private keys if git diff --cached | grep -q "BEGIN.*PRIVATE KEY"; then echo "❌ Private key detected in commit!" exit 1 fi # Check for passwords if git diff --cached | grep -iqE "password\s*=\s*.+"; then echo "❌ Potential password detected in commit!" exit 1 fi EOF chmod +x .git/hooks/pre-commit
Part 3: CI/CD Security
SAST (Static Application Security Testing)
SAST analyzes source code for security vulnerabilities without running the application.
GitHub Actions with Semgrep:
name: SAST on: [push, pull_request] jobs: semgrep: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Semgrep scan uses: returntocorp/semgrep-action@v1 with: config: >- p/security-audit p/secrets p/owasp-top-ten
GitLab CI with SAST:
include: - template: Security/SAST.gitlab-ci.yml variables: SAST_EXCLUDED_PATHS: "spec, test, tests, tmp"
SCA (Software Composition Analysis)
SCA scans dependencies for known vulnerabilities.
GitHub Actions with Snyk:
name: SCA on: [push] jobs: snyk: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: snyk/actions/node@master env: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} with: args: --severity-threshold=high
OWASP Dependency-Check (Java, Node.js, Python):
- name: OWASP Dependency Check uses: dependency-check/Dependency-Check_Action@main with: project: 'My App' path: '.' format: 'HTML' out: 'reports'
Secret Scanning in CI
name: Secret Scanning on: [push] jobs: trufflehog: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: TruffleHog scan uses: trufflesecurity/trufflehog@main with: path: ./ base: ${{ github.event.repository.default_branch }} head: HEAD
Part 4: Container Security
Dockerfile Security Best Practices
# ❌ Bad practices FROM node:latest # latest tag is unpredictable RUN npm install # No version pinning COPY . . # No .dockerignore USER root # Running as root ENV SECRET=value # Secrets in image # ✅ Good practices FROM node:18.17.0-alpine RUN npm ci --only=production COPY --chown=node:node . . USER node # Use secrets at runtime, never build time
Container Image Scanning
Trivy (most popular):
# Install Trivy brew install aquasecurity/trivy/trivy # Scan Docker image trivy image myapp:latest # Scan with severity filter trivy image --severity HIGH,CRITICAL myapp:latest # Scan in CI trivy image --exit-code 1 --severity CRITICAL myapp:latest
GitHub Actions with Trivy:
name: Container Scan on: push: paths: - 'Dockerfile' jobs: trivy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Build image run: docker build -t myapp:test . - name: Scan image uses: aquasecurity/trivy-action@master with: image-ref: myapp:test format: 'sarif' output: 'trivy-results.sarif' severity: 'CRITICAL,HIGH' - name: Upload results uses: github/codeql-action/upload-sarif@v2 with: sarif_file: 'trivy-results.sarif'
Grype (from Anchore):
grype myapp:latest --fail-on high
Part 5: Infrastructure as Code Security
Terraform Scanning
Checkov (Comprehensive policy scanning):
# Install Checkov pip install checkov # Scan Terraform directory checkov -d . # Scan with specific framework checkov -d . --framework terraform # GitHub Action - name: Checkov scan uses: bridgecrewio/checkov-action@master with: directory: ./ framework: terraform output_format: cli
tfsec (Focused on Terraform):
# Install tfsec brew install aquasecurity/tfsec/tfsec # Scan directory tfsec . # Critical policies only tfsec --severity CRITICAL # GitHub Action - name: tfsec uses: aquasecurity/tfsec-action@v1.0.0
Key security policies to enforce:
| Policy | Why It Matters |
|---|---|
| S3 bucket not public | Prevent data exposure |
| Encryption enabled | Protect data at rest |
| No security group 0.0.0.0/0 to port 22 | Prevent SSH brute force |
| IAM least privilege | Limit breach impact |
| Versioning enabled | Recover from mistakes |
Kubernetes Security Scanning
kube-score (YAML validation):
kube-score score manifest.yaml
kube-bench (CIS benchmarks):
# Run on cluster docker run --pid=host -v /etc:/etc:ro -v /var:/var:ro aquasec/kube-bench
Popeye (Cluster health):
popeye --savePart 6: DAST (Dynamic Application Security Testing)
DAST tests running applications for vulnerabilities by simulating attacks.
OWASP ZAP
# GitHub Actions with OWASP ZAP name: DAST on: deployment_status: jobs: zap: runs-on: ubuntu-latest steps: - name: ZAP Scan uses: zaproxy/action-full-scan@v0.4.0 with: target: ${{ github.event.deployment_status.environment_url }} rules_file_name: '.zap/rules.tsv' cmd_options: '-a'
Automated DAST in CI/CD
# Deploy staging, then scan deploy-staging: stage: deploy script: - kubectl apply -f manifest.yaml dast: stage: test needs: [deploy-staging] image: owasp/zap2docker-stable script: - zap-full-scan.py -t https://staging.example.com -r report.html artifacts: paths: - report.html
Part 7: Runtime Security
Falco (Runtime Security)
Falco monitors system calls and detects unexpected behavior.
Install Falco:
helm install falco falcosecurity/falco \ --namespace falco \ --create-namespace
Falco Rules Example:
- rule: Write below binary dir desc: an attempt to write to any file below /bin condition: > open_write and fd.directory in (/bin, /sbin, /usr/bin, /usr/sbin) output: > File below a binary directory opened for writing (user=%user.name command=%proc.cmdline file=%fd.name parent=%proc.pname) priority: CRITICAL
AppArmor (Linux Kernel Security)
# Kubernetes Pod with AppArmor apiVersion: v1 kind: Pod metadata: name: secured-pod annotations: container.apparmor.security.beta.kubernetes.io/app: localhost/my-profile spec: containers: - name: app image: nginx
Seccomp (System Call Filtering)
# Pod with seccomp profile apiVersion: v1 kind: Pod metadata: name: secured-pod spec: securityContext: seccompProfile: type: RuntimeDefault containers: - name: app image: nginx
Part 8: Complete DevSecOps Pipeline (GitHub Actions)
name: DevSecOps Pipeline on: push: branches: [ main, develop ] pull_request: branches: [ main ] jobs: pre-commit-checks: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Secret detection uses: gitleaks/gitleaks-action@v2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} sast: runs-on: ubuntu-latest needs: pre-commit-checks steps: - uses: actions/checkout@v4 - name: Semgrep scan uses: returntocorp/semgrep-action@v1 with: config: >- p/security-audit p/secrets p/owasp-top-ten sca: runs-on: ubuntu-latest needs: pre-commit-checks steps: - uses: actions/checkout@v4 - name: Snyk scan uses: snyk/actions/node@master env: SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} with: args: --severity-threshold=high container-scan: runs-on: ubuntu-latest needs: [sast, sca] if: github.ref == 'refs/heads/main' steps: - uses: actions/checkout@v4 - 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' output: 'trivy-results.sarif' severity: 'CRITICAL,HIGH' - name: Upload SARIF uses: github/codeql-action/upload-sarif@v2 with: sarif_file: 'trivy-results.sarif' iac-scan: runs-on: ubuntu-latest needs: pre-commit-checks steps: - uses: actions/checkout@v4 - name: Checkov scan uses: bridgecrewio/checkov-action@master with: directory: ./terraform framework: terraform output_format: cli - name: tfsec scan uses: aquasecurity/tfsec-action@v1.0.0 with: working_directory: ./terraform dast: runs-on: ubuntu-latest needs: [container-scan] if: github.ref == 'refs/heads/main' environment: staging steps: - name: ZAP Scan uses: zaproxy/action-full-scan@v0.4.0 with: target: https://staging.example.com allow_issue_writing: true token: ${{ secrets.GITHUB_TOKEN }} deploy: runs-on: ubuntu-latest needs: [dast, iac-scan] if: github.ref == 'refs/heads/main' environment: production steps: - name: Deploy to production run: | echo "Deploying with security verified" # Your deployment steps
Part 9: Security Tools Summary
| Category | Tool | Best For |
|---|---|---|
| Secret Detection | detect-secrets, truffleHog | Pre-commit scanning |
| SAST | Semgrep, SonarQube | Code vulnerabilities |
| SCA | Snyk, OWASP Dependency-Check | Dependency vulnerabilities |
| Container | Trivy, Grype | Image vulnerabilities |
| IaC | Checkov, tfsec | Infrastructure misconfigurations |
| DAST | OWASP ZAP | Runtime vulnerabilities |
| Runtime | Falco | Behavioral anomalies |
DevSecOps Best Practices
Shift Left
Run security tests as early as possible in the pipeline
Fail builds on critical vulnerabilities
Provide developers with immediate feedback
Automate Everything
No manual security gates
All security testing should be automated
Use infrastructure as code for security controls
Defense in Depth
Multiple layers of security (SAST, SCA, DAST, runtime)
Assume any layer might fail
Never rely on a single control
Continuous Improvement
Track security metrics over time
Reduce false positives
Update security rules regularly
DevSecOps Checklist
Pre-Commit
Secret scanning enabled
Pre-commit hooks configured
IDE security plugins installed
CI Pipeline
SAST running on every commit
SCA checking dependencies
Container image scanning
Infrastructure code scanning
Staging
DAST running on deployment
Security regression tests
Penetration testing schedule
Production
Runtime security monitoring
Vulnerability scanning schedule
Incident response plan
Regular security training
Common DevSecOps Interview Questions
Q: What is the difference between SAST and DAST?
A: SAST (Static Application Security Testing) analyzes source code without running the application. It finds issues early but may have false positives. DAST (Dynamic Application Security Testing) tests running applications and finds runtime issues but requires a deployed environment.
Q: How do you prioritize security vulnerabilities?
A: Use a risk-based approach: severity (CVSS score), exploitability (public exploits exist), impact (data loss, downtime), and asset criticality. Critical and high severity issues in production should be fixed immediately.
Q: What is shift-left security?
A: Shift-left means moving security testing earlier in the development lifecycle. Finding a vulnerability in code costs $80. Finding it in production costs $8,000. Shift-left saves money and time.
Q: How do you handle false positives in security scanning?
A:
Tune tools with.ignore files
Create baseline exceptions
Regularly review and remove old exceptions
Use multiple tools to cross-validate
Summary
DevSecOps is not a tool or a role. It is a culture of shared security responsibility.
| Stage | Practice | Tool |
|---|---|---|
| Code | Secret detection | detect-secrets |
| Commit | SAST | Semgrep |
| Build | SCA | Snyk |
| Container | Image scan | Trivy |
| IaC | Configuration scan | Checkov |
| Deploy | DAST | OWASP ZAP |
| Runtime | Behavior monitoring | Falco |
Start small. Add one security check at a time. Build momentum. Make security everyone's job.
Learn More
Practice DevSecOps with hands-on exercises in our interactive labs:
https://devops.trainwithsky.com/
Comments
Post a Comment