Application Security
DevSecOps & CI/CD Security
4 min read
DevSecOps integrates security into every phase of software development. This lesson covers the pipeline security practices and tools you'll discuss in interviews.
The Shift-Left Approach
Traditional Security: Shift-Left Security:
Design → Dev → Test → Deploy → Security Security → Design → Dev → Test → Deploy
↑ | ↓ ↓ ↓ ↓
└────── Expensive fixes ─┘ Early detection throughout pipeline
Cost of Fixing Bugs by Phase
| Phase | Relative Cost | Example |
|---|---|---|
| Design | 1x | Threat model identifies flaw |
| Development | 5x | Code review catches issue |
| Testing | 10x | DAST finds vulnerability |
| Production | 100x | Breach response and remediation |
Secure CI/CD Pipeline
# .github/workflows/security.yaml
name: Security Pipeline
on: [push, pull_request]
jobs:
security-scan:
runs-on: ubuntu-latest
steps:
# 1. Secret scanning
- name: Secret Detection
uses: trufflesecurity/trufflehog@main
with:
path: ./
base: ${{ github.event.repository.default_branch }}
# 2. SAST - Static Analysis
- name: Run Semgrep
uses: returntocorp/semgrep-action@v1
with:
config: >-
p/security-audit
p/owasp-top-ten
# 3. SCA - Dependency Scanning
- name: Dependency Check
uses: snyk/actions/node@master
with:
args: --severity-threshold=high
# 4. Container Scanning
- name: Scan Docker Image
uses: aquasecurity/trivy-action@master
with:
image-ref: '${{ github.repository }}:${{ github.sha }}'
severity: 'CRITICAL,HIGH'
# 5. Infrastructure as Code
- name: Terraform Security
uses: aquasecurity/tfsec-action@v1.0.0
Security Gates
Breaking the Build
# security_gate.py - CI/CD security enforcement
class SecurityGate:
def __init__(self, config):
self.severity_threshold = config.get('severity_threshold', 'HIGH')
self.max_vulnerabilities = config.get('max_vulnerabilities', 0)
def evaluate(self, scan_results):
critical = scan_results.get('critical', 0)
high = scan_results.get('high', 0)
# Always fail on critical findings
if critical > 0:
return {
'pass': False,
'reason': f'{critical} critical vulnerabilities found'
}
# Configurable threshold for high severity
if self.severity_threshold == 'HIGH' and high > self.max_vulnerabilities:
return {
'pass': False,
'reason': f'{high} high severity issues exceed threshold'
}
return {'pass': True, 'reason': 'Security checks passed'}
Secrets Management
What NOT to Do
# NEVER do this
env:
DATABASE_URL: "postgres://admin:password123@db.example.com/prod"
API_KEY: "sk-live-abc123xyz789"
Secure Secrets Handling
# GitHub Actions with secrets
jobs:
deploy:
steps:
- name: Configure AWS
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
- name: Get Secrets
uses: aws-actions/aws-secretsmanager-get-secrets@v2
with:
secret-ids: |
DB_CREDENTIALS,prod/database
API_KEYS,prod/api-keys
Interview Question
Q: "How would you handle secrets in a CI/CD pipeline?"
Answer:
- Never commit secrets - Use .gitignore, pre-commit hooks
- Use secrets managers - AWS Secrets Manager, HashiCorp Vault, GitHub Secrets
- Rotate regularly - Automated rotation with versioning
- Audit access - Log who accesses secrets, when
- Least privilege - Only inject secrets needed for each job
- Scan for leaks - TruffleHog, GitLeaks in pre-commit
Container Security
Dockerfile Best Practices
# Bad: Using root, large image, no scanning
FROM ubuntu:latest
RUN apt-get update && apt-get install -y python3
COPY . /app
CMD ["python3", "/app/main.py"]
# Good: Non-root, minimal image, pinned versions
FROM python:3.12-slim-bookworm AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
FROM gcr.io/distroless/python3-debian12
COPY /app /app
COPY . /app
USER nonroot
ENTRYPOINT ["python", "/app/main.py"]
Container Scanning Pipeline
- name: Build and Scan
run: |
docker build -t myapp:${{ github.sha }} .
# Scan for vulnerabilities
trivy image --exit-code 1 --severity HIGH,CRITICAL myapp:${{ github.sha }}
# Check for secrets
docker run --rm -v $(pwd):/path trufflehog filesystem /path
# Verify base image
docker run --rm aquasec/trivy image python:3.12-slim
Infrastructure as Code Security
Terraform Security Scanning
# BAD: Overly permissive S3 bucket
resource "aws_s3_bucket" "data" {
bucket = "company-data"
acl = "public-read" # tfsec will flag this
}
# GOOD: Private bucket with encryption
resource "aws_s3_bucket" "data" {
bucket = "company-data"
}
resource "aws_s3_bucket_public_access_block" "data" {
bucket = aws_s3_bucket.data.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
resource "aws_s3_bucket_server_side_encryption_configuration" "data" {
bucket = aws_s3_bucket.data.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "aws:kms"
}
}
}
Security Metrics
Track these in your security dashboard:
| Metric | Target | Why It Matters |
|---|---|---|
| Mean Time to Remediate (MTTR) | < 7 days (critical) | Response speed |
| Vulnerability Density | < 1 per 1000 LOC | Code quality |
| False Positive Rate | < 10% | Tool effectiveness |
| Pipeline Block Rate | Track trend | Security culture |
| Secrets Detected | 0 in production | Data protection |
Interview Tip: Emphasize that DevSecOps is about culture, not just tools. Discuss how you would build security champions programs and enable developers to fix issues independently.
In the next module, we'll cover cloud and infrastructure security. :::