DevSecOps — Security Embedded in the Pipeline
Embed security into every phase of the SDLC without slowing delivery. Build SAST/DAST/SCA gates, secure CI/CD pipelines, scan infrastructure-as-code, manage secrets, and build a security culture where developers own security outcomes.
What Is DevSecOps?
DevSecOps integrates security practices into the DevOps workflow — making security a shared responsibility across development, operations, and security teams rather than a gating function that sits at the end. The goal is to catch and fix security issues as early as possible in the development lifecycle, where fixes are cheapest.
The core shift: security moves from "gate at the end" (slow, confrontational, finds issues too late) to "guardrail throughout" (fast, collaborative, fixes issues when context is fresh). Developers do not become security experts; security becomes part of their normal workflow.
The DevSecOps Toolchain by Phase
SDLC Phase | Security Activity | Key Tools
─────────────────────────────────────────────────────────────────
Plan / Design | Threat modelling | OWASP Threat Dragon, Miro
| Security requirements | OWASP ASVS
─────────────────────────────────────────────────────────────────
Code | IDE security plugins | Semgrep, Snyk (IDE)
| Pre-commit hooks | gitleaks, detect-secrets
─────────────────────────────────────────────────────────────────
Build / CI | SAST (Static Analysis) | Semgrep, CodeQL, Checkmarx
| SCA (dependency vuln) | Trivy, Snyk, OWASP DC
| Secret scanning | Gitleaks, TruffleHog
| Container image scanning | Trivy, Grype, Clair
| IaC scanning | Checkov, tfsec, KICS
─────────────────────────────────────────────────────────────────
Test / DAST | DAST (Dynamic Analysis) | OWASP ZAP, Burp Suite
| API security testing | ZAP API scan, Dredd
─────────────────────────────────────────────────────────────────
Deploy | Image signing | Cosign, Notary
| Runtime policy enforcement | OPA/Gatekeeper, Kyverno
─────────────────────────────────────────────────────────────────
Operate | Runtime security monitoring | Falco, Sysdig
| CSPM (cloud posture) | Wiz, Orca, AWS Security Hub
| VM scanning | Tenable, Qualys
─────────────────────────────────────────────────────────────────
Monitor / Respond | SIEM, EDR, threat hunting | Splunk, CrowdStrike (Module 31/34)Security Champions Programme
A Security Champions programme embeds one or two security-enthusiastic developers in each engineering team. They are not security experts — they are a bridge, translating security requirements into developer language, running threat models in sprint planning, and being the first call when the SAST scanner fires.
Security Champions model: Role: Developer in an engineering team, not a separate security team member Time: 10-20% of their sprint allocation Responsibilities: - Run threat model sessions for new features (30-min structured session) - Triage SAST/SCA findings for their team — filter false positives - Review PR security concerns (not a full security review — spot check) - Attend monthly champions meeting (share patterns, get training) - Escalate to central security team when needed Security team's role: - Run training programme (quarterly workshops) - Provide tooling and runbooks - Handle escalations and policy questions - NOT: review every PR, block every deployment Metrics to track: - Time from SAST finding to ticket creation (target: same day) - Champion engagement: attendance, PRs reviewed - Security debt trend by team
SAST — Static Analysis in CI
SAST tools analyse source code for security issues without executing it. They are fast enough to run on every commit and give developers immediate feedback at the point of introduction — when context is fresh and the fix is straightforward.
Semgrep — Rules-Based SAST
# Install Semgrep
pip install semgrep
# Scan with OWASP Top 10 ruleset
semgrep --config "p/owasp-top-ten" ./src/
# Scan with multiple rulesets
semgrep --config "p/python" --config "p/javascript" --config "p/secrets" ./
# Run with SARIF output (for GitHub Code Scanning upload)
semgrep --config "p/owasp-top-ten" --sarif --output semgrep.sarif ./
# Custom rule — detect hardcoded AWS credentials
# File: rules/hardcoded_aws.yml
rules:
- id: hardcoded-aws-access-key
patterns:
- pattern: |
$KEY = "AKIA..."
message: "Hardcoded AWS access key detected. Use environment variables or secrets manager."
languages: [python, javascript, typescript, go, java]
severity: ERROR
metadata:
cwe: "CWE-798: Use of Hard-coded Credentials"
owasp: "A07:2021 - Identification and Authentication Failures"
semgrep --config rules/hardcoded_aws.yml ./CodeQL — Deep Semantic Analysis
# CodeQL analyses code as a database of relationships — finds complex multi-step vulnerabilities
# Free for open source; GitHub Advanced Security for private repos
# GitHub Actions — CodeQL analysis
name: CodeQL Analysis
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
- cron: '0 2 * * 1' # weekly full scan
jobs:
analyze:
runs-on: ubuntu-latest
permissions:
security-events: write
actions: read
strategy:
matrix:
language: [javascript, python] # add java, go, csharp, ruby, swift as needed
steps:
- uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
queries: security-extended # more rules than default
- name: Autobuild
uses: github/codeql-action/autobuild@v3
- name: Run CodeQL analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{ matrix.language }}"
output: results/
upload: trueManaging SAST False Positives
SAST false positive management strategy: Rule 1: Never suppress without investigation Bad: # nosemgrep: hardcoded-password (blindly suppressing) Good: Understand WHY it fired, confirm it is a FP, document why Rule 2: Suppress at rule level with justification # Python Semgrep suppression (inline) password_check = validate_password(input_pw) # nosemgrep: hardcoded-password # This is a function call, not a hardcoded value — rule is confused by variable name Rule 3: Track suppression rate - High suppression rate = bad rule (tune or disable) - Low suppression rate = rule is high-value (keep) Rule 4: Create team-specific baselines - First run: scan existing code, baseline all existing findings - Going forward: only NEW findings block the build - Existing findings tracked separately for remediation sprint Rule 5: Monthly FP review with champions - Review top 10 most-suppressed rules - Tune or remove rules with > 80% FP rate
SCA — Software Composition Analysis
Open source makes up 70-90% of modern application code. SCA tools inventory these dependencies and alert when known vulnerabilities are discovered in them. Supply chain attacks have made SCA more critical than ever — attackers now target libraries used by thousands of downstream applications.
Dependency Scanning with Trivy and Snyk
# Trivy — fast, comprehensive, open-source SCA
# Scan application dependencies
trivy fs . --scanners vuln --severity CRITICAL,HIGH --format table
trivy fs . --scanners vuln --format sarif --output trivy.sarif
# Scan a container image
trivy image python:3.11-slim --severity CRITICAL,HIGH
# Scan with secret detection and IaC
trivy fs . --scanners vuln,misconfig,secret
# JSON output for CI integration
trivy fs . --format json --output trivy-results.json
python -c "
import json
data = json.load(open('trivy-results.json'))
for result in data.get('Results', []):
for vuln in result.get('Vulnerabilities', []):
if vuln['Severity'] in ['CRITICAL', 'HIGH']:
print(f"{vuln['VulnerabilityID']}: {vuln['PkgName']} {vuln.get('InstalledVersion')} -> {vuln.get('FixedVersion', 'no fix')} [{vuln['Severity']}]")
"
# Snyk CLI (free tier available, better developer UX)
npm install -g snyk
snyk auth # authenticate
snyk test # scan current project
snyk test --severity-threshold=high # only fail on high+
snyk monitor # continuous monitoring (sends to Snyk cloud)
snyk container test nginx:latest # container scanningOWASP Dependency Check
# OWASP Dependency-Check — mature, Java-based, supports many ecosystems # Download: https://owasp.org/www-project-dependency-check/ dependency-check --scan ./lib/ --format HTML --out reports/ dependency-check --scan pom.xml --format JSON --out reports/ # Maven plugin (Java projects) # Add to pom.xml: # <plugin> # <groupId>org.owasp</groupId> # <artifactId>dependency-check-maven</artifactId> # <version>9.0.0</version> # <configuration> # <failBuildOnCVSS>7</failBuildOnCVSS> <!-- fail on CVSS >= 7 --> # </configuration> # </plugin> mvn dependency-check:check # npm audit (built-in, run in any Node.js project) npm audit npm audit --audit-level=high # exit non-zero only on high+ npm audit fix # auto-fix compatible updates npm audit fix --force # fix including breaking changes (review carefully)
Supply Chain Security
Supply chain attack vectors and mitigations: THREAT: Malicious package published with typosquatted name (e.g., "colourama" instead of "colorama") MITIGATION: - Use exact package names and versions in lock files - Enable private registry mirroring (Artifactory, Nexus) - Require package hash verification in requirements.txt / package-lock.json THREAT: Compromised maintainer account — malicious code injected into legit package (SolarWinds, XZ Utils, event-stream incidents) MITIGATION: - Pin to specific commit hash or verified release tag, not mutable version tag - Enable Dependabot / Renovate for automated update PRs with diff review - Audit major dependency updates manually before merging THREAT: Dependency confusion — private package name scooped by attacker on public registry (Alex Birsan's 2021 research — affected Apple, Microsoft, PayPal) MITIGATION: - Register your private package names on public registries (empty placeholder) - Use scoped packages (@company/package-name) - Configure pip/npm to use private registry with fallback disabled # Sigstore — cryptographically sign and verify release artefacts # Verify a Python package signature pip install sigstore python -m sigstore verify identity --bundle package.sigstore --cert-identity maintainer@example.com --cert-oidc-issuer https://accounts.google.com package-1.0.tar.gz
Secrets Management in CI/CD
Secrets (API keys, database passwords, TLS certificates, cloud credentials) are the most common cause of cloud breaches. A secret committed to a Git repository — even briefly — must be treated as permanently compromised: GitHub indexes all public repos immediately and attackers scan for leaked secrets in near-real-time.
Preventing Secrets from Entering Version Control
# Pre-commit hook — gitleaks scans every commit before it is recorded
# Install gitleaks
brew install gitleaks
# Manual scan — check entire repo history
gitleaks detect --source . --verbose
# Scan staged changes only (for pre-commit hook use)
gitleaks protect --staged
# Install as pre-commit hook (using pre-commit framework)
# .pre-commit-config.yaml
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.18.4
hooks:
- id: gitleaks
# detect-secrets — alternative, integrates well with Python projects
pip install detect-secrets
detect-secrets scan > .secrets.baseline # baseline known non-secrets
detect-secrets scan --baseline .secrets.baseline # only flag new findings
# TruffleHog — scans git history for secrets (GitHub Actions integration)
trufflehog git file://. --only-verified # only report verified live secretsSecrets in CI/CD Pipelines
# GitHub Actions — correct secrets usage
jobs:
deploy:
steps:
- name: Deploy to AWS
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run: aws s3 sync ./dist s3://my-bucket/
# NEVER do this in GitHub Actions:
# run: aws configure set aws_access_key_id AKIAIOSFODNN7EXAMPLE (hardcoded!)
# run: echo $MY_SECRET (leaks secret to logs)
# Log masking: GitHub automatically masks values of secrets
# But: if you split/transform a secret, the masked value changes and may leak
# Example of what NOT to do:
# run: echo ${{ secrets.API_KEY }} | cut -c1-5 (partial key may appear in logs)
# HashiCorp Vault — enterprise secrets management
# Inject secrets at runtime, not at build time
vault kv get -field=password secret/myapp/database
# GitHub Actions + Vault (OIDC — no long-lived credentials needed)
- name: Import Vault Secrets
uses: hashicorp/vault-action@v3
with:
url: https://vault.company.com
method: jwt
role: github-actions-role
secrets: |
secret/data/myapp/database password | DB_PASSWORD ;
secret/data/myapp/api key | API_KEYResponding to a Leaked Secret
Leaked secret response (treat as immediate P1): Step 1 — Revoke IMMEDIATELY (do not wait to confirm misuse) - AWS key: aws iam delete-access-key --access-key-id AKIA... - GitHub token: Settings > Developer settings > Personal access tokens > Revoke - Database password: ALTER USER app_user WITH PASSWORD 'new_secure_password'; Step 2 — Audit usage (what happened while it was exposed?) - AWS: CloudTrail logs for the compromised key - GitHub: audit log for the token's activity - GCP: Cloud Audit Logs Step 3 — Remove from git history # git-filter-repo (preferred — replaces BFG Repo Cleaner) pip install git-filter-repo git filter-repo --path-glob '*.env' --invert-paths git filter-repo --replace-text <(echo "AKIA_BADKEY==>REDACTED") git push --force # force push after history rewrite # IMPORTANT: All collaborators must re-clone — their local copies still have the secret # GitHub: contact support to purge cached views Step 4 — Issue new secret and rotate dependent systems Step 5 — Add detection: gitleaks pre-commit hook + TruffleHog in CI
Container and Kubernetes Security
Container security starts with the image and extends through the runtime. A misconfigured container running as root with host networking is often more dangerous than a vulnerable dependency inside it.
Secure Dockerfile Practices
# Insecure Dockerfile — 5 problems FROM ubuntu:latest # mutable tag — breaks reproducibility RUN apt-get install python3 -y # installs without pinning versions COPY . /app RUN pip install -r requirements.txt EXPOSE 22 # SSH in a container — always wrong USER root # explicitly running as root CMD ["python", "app.py"] # Secure Dockerfile — all problems fixed FROM python:3.11.9-slim # pinned version, minimal base WORKDIR /app # Install dependencies as root (required), then drop privileges COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # Copy application code COPY --chown=appuser:appuser . . # Create non-root user (before COPY if possible) RUN groupadd -r appuser && useradd -r -g appuser appuser USER appuser # run as non-root EXPOSE 8080 # document the port used, not SSH HEALTHCHECK --interval=30s --timeout=5s CMD curl -f http://localhost:8080/health || exit 1 CMD ["python", "-u", "app.py"]
Kubernetes Security — Pod Security Standards
# Kubernetes Pod Security Standards (PSS) — built-in policy framework
# Three profiles: Privileged, Baseline, Restricted
# Apply Restricted profile to a namespace (denies privilege escalation)
kubectl label namespace production pod-security.kubernetes.io/enforce=restricted
kubectl label namespace production pod-security.kubernetes.io/warn=restricted
# Secure Pod spec — enforces all Restricted profile requirements
apiVersion: v1
kind: Pod
metadata:
name: secure-app
spec:
securityContext:
runAsNonRoot: true # reject if container tries to run as root
runAsUser: 1000 # specific UID
runAsGroup: 3000
fsGroup: 2000
seccompProfile:
type: RuntimeDefault # restrict syscalls to default profile
containers:
- name: app
image: myapp:1.2.3@sha256:abc123... # pin by digest (immutable)
securityContext:
allowPrivilegeEscalation: false # no sudo/setuid
readOnlyRootFilesystem: true # prevent in-container modification
capabilities:
drop: ["ALL"] # drop all Linux capabilities
resources:
limits:
memory: "256Mi"
cpu: "500m"
requests:
memory: "128Mi"
cpu: "100m"Runtime Security with Falco
# Falco — runtime security monitoring for containers and Linux hosts
# Detects anomalous behaviour at kernel syscall level
# Install Falco (Helm chart — Kubernetes)
helm repo add falcosecurity https://falcosecurity.github.io/charts
helm install falco falcosecurity/falco --namespace falco --create-namespace --set driver.kind=ebpf --set falcosidekick.enabled=true --set falcosidekick.config.slack.webhookurl=https://hooks.slack.com/...
# Example Falco rules (in /etc/falco/falco_rules.yaml):
# Alert: shell spawned in a container
- rule: Shell Spawned in Container
desc: A shell was spawned in a container
condition: >
spawned_process and container and
proc.name in (shell_binaries) and
not proc.pname in (shell_binaries) and
not container.image.repository in (allowed_shell_images)
output: >
Shell spawned in container (container=%container.name
image=%container.image.repository cmd=%proc.cmdline
user=%user.name)
priority: WARNING
tags: [container, shell, T1059]
# Alert: sensitive file read in container
- rule: Read sensitive file in container
desc: Attempt to read sensitive host file in container
condition: >
open_read and container and
fd.name in (/etc/shadow, /etc/passwd, /root/.ssh/authorized_keys)
output: "Sensitive file read (container=%container.name file=%fd.name)"
priority: ERROROPA/Gatekeeper — Policy as Code
# Open Policy Agent (OPA) + Gatekeeper enforce Kubernetes admission policies
# Gatekeeper intercepts every resource creation and runs OPA policy
# ConstraintTemplate — define the policy rule
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8srequiredlabels
spec:
crd:
spec:
names:
kind: K8sRequiredLabels
validation:
openAPIV3Schema:
properties:
labels:
type: array
items: {type: string}
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8srequiredlabels
violation[{"msg": msg}] {
provided := {label | input.review.object.metadata.labels[label]}
required := {label | label := input.parameters.labels[_]}
missing := required - provided
count(missing) > 0
msg := sprintf("Missing required labels: %v", [missing])
}
# Constraint — apply the policy
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
name: require-owner-label
spec:
match:
kinds:
- apiGroups: ["apps"]
kinds: ["Deployment"]
parameters:
labels: ["owner", "env", "team"]Infrastructure as Code Security
IaC (Terraform, CloudFormation, Kubernetes YAML, Helm) defines infrastructure programmatically — which means infrastructure misconfigurations can be caught in code review before they are deployed. IaC scanning applies the same shift-left principle to infrastructure that SAST applies to application code.
Checkov — Multi-Framework IaC Scanner
# Checkov scans Terraform, CloudFormation, Kubernetes, Dockerfiles, ARM, Bicep
pip install checkov
# Scan a Terraform directory
checkov -d ./terraform/ --framework terraform
# Scan with specific checks only
checkov -d ./terraform/ --check CKV_AWS_18,CKV_AWS_21
# Scan Kubernetes manifests
checkov -d ./kubernetes/ --framework kubernetes
# Example findings Checkov catches:
# CKV_AWS_18: S3 bucket should have access logging enabled
# CKV_AWS_21: S3 bucket should have versioning enabled
# CKV_AWS_78: EKS cluster should have secrets encryption enabled
# CKV_K8S_14: Container should not run with allowPrivilegeEscalation = true
# CKV_K8S_28: Container should not run in privileged mode
# GitHub Actions — Checkov in CI
- name: Run Checkov IaC scan
uses: bridgecrewio/checkov-action@master
with:
directory: terraform/
framework: terraform
output_format: sarif
output_file_path: results.sarif
soft_fail: false # fail the build on HIGH+ findingsTerraform Security Patterns
# Insecure S3 bucket (common misconfiguration)
resource "aws_s3_bucket" "data" {
bucket = "company-data"
}
# Missing: public access block, versioning, encryption, logging
# Secure S3 bucket (all controls applied)
resource "aws_s3_bucket" "data" {
bucket = "company-data-prod"
}
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_versioning" "data" {
bucket = aws_s3_bucket.data.id
versioning_configuration { status = "Enabled" }
}
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"
kms_master_key_id = aws_kms_key.s3_key.arn
}
}
}
resource "aws_s3_bucket_logging" "data" {
bucket = aws_s3_bucket.data.id
target_bucket = aws_s3_bucket.logs.id
target_prefix = "s3-access-logs/"
}Cloud Security Posture Management (CSPM)
CSPM tools continuously scan cloud infrastructure for misconfigurations: Commercial (widely used in enterprise): - Wiz: agentless, visualises entire cloud attack surface + blast radius - Orca Security: similar agentless approach, strong compliance reporting - Prisma Cloud: Palo Alto product, broad compliance framework coverage AWS-native (free with AWS): - AWS Security Hub: aggregates findings from GuardDuty, Inspector, Config, Macie - AWS Config: tracks resource configuration changes, runs conformance packs - Amazon GuardDuty: ML-based threat detection on CloudTrail, VPC Flow, DNS logs - Amazon Inspector: EC2 + ECR vulnerability scanning, agentless Multi-cloud open-source: - Prowler: CLI tool, 500+ checks, outputs CSV/JSON/HTML - ScoutSuite: multi-cloud security auditing tool - CloudSploit: open-source CSPM # Prowler — run all AWS checks pip install prowler prowler aws --output-formats html,json # AWS Security Hub — enable all standards aws securityhub enable-security-hub --enable-default-standards aws securityhub enable-standards --standards-subscription-requests StandardsArn=arn:aws:securityhub:::ruleset/cis-aws-foundations-benchmark/v/1.4.0
Complete Secure CI/CD Pipeline
Reference Pipeline — GitHub Actions
# Full DevSecOps pipeline — end to end
name: Secure Build and Deploy
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
IMAGE_NAME: myapp
REGISTRY: ghcr.io/myorg
jobs:
# ── Phase 1: Code Security ────────────────────────────────────────
secret-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }
- uses: gitleaks/gitleaks-action@v2
env: { GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} }
sast:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: semgrep/semgrep-action@v1
with:
config: "p/owasp-top-ten p/python p/secrets"
publishResults: true
codeql:
runs-on: ubuntu-latest
permissions: { security-events: write, actions: read, contents: read }
steps:
- uses: actions/checkout@v4
- uses: github/codeql-action/init@v3
with: { languages: python }
- uses: github/codeql-action/autobuild@v3
- uses: github/codeql-action/analyze@v3
# ── Phase 2: Dependencies ─────────────────────────────────────────
sca:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Trivy SCA
run: |
trivy fs . --scanners vuln --severity CRITICAL,HIGH --exit-code 1 --format sarif --output trivy-sca.sarif
- uses: github/codeql-action/upload-sarif@v3
with: { sarif_file: trivy-sca.sarif }
if: always()
# ── Phase 3: IaC ─────────────────────────────────────────────────
iac-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: bridgecrewio/checkov-action@master
with:
directory: terraform/
framework: terraform
output_format: sarif
output_file_path: checkov.sarif
- uses: github/codeql-action/upload-sarif@v3
with: { sarif_file: checkov.sarif }
if: always()
# ── Phase 4: Build and Container Scan ────────────────────────────
build:
needs: [secret-scan, sast, sca, iac-scan]
runs-on: ubuntu-latest
outputs:
digest: ${{ steps.push.outputs.digest }}
steps:
- uses: actions/checkout@v4
- uses: docker/build-push-action@v5
id: build
with:
push: false
tags: ${{ env.IMAGE_NAME }}:ci
load: true
- name: Trivy container scan
run: |
trivy image ${{ env.IMAGE_NAME }}:ci --severity CRITICAL,HIGH --exit-code 1
- name: Push to registry (main branch only)
if: github.ref == 'refs/heads/main'
id: push
uses: docker/build-push-action@v5
with:
push: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
# ── Phase 5: DAST (staging) ───────────────────────────────────────
dast:
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- name: Deploy to staging
run: kubectl set image deployment/myapp app=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
- name: ZAP API Scan
uses: zaproxy/action-api-scan@v0.9.0
with:
target: https://staging.company.com/api/openapi.json
fail_action: true🎯 Key Takeaways
- ✓DevSecOps shifts security from an end-of-pipeline gate to a continuous guardrail — catching issues when they are cheapest to fix, not when they are hardest.
- ✓SAST finds code-level issues without running the app (runs on every commit), SCA finds vulnerable dependencies (continuous), and DAST tests the running application (pre-production) — all three together provide layered coverage.
- ✓Security Champions embed security into engineering teams: they are developers, not security staff, and act as translators between the security team and their engineering team.
- ✓SAST false positive rate must be kept below 20% — above that, developers suppress alerts by default and real vulnerabilities get lost in the noise.
- ✓A secret committed to a public Git repository is permanently compromised the moment it is pushed — revoke immediately, then clean history and audit for misuse.
- ✓Container images should run as non-root, use a pinned minimal base image, drop all Linux capabilities, and have a read-only root filesystem.
- ✓IaC scanning (Checkov, tfsec) must run in CI on every PR that modifies infrastructure — misconfigurations caught in code review cost nothing to fix; misconfigurations found post-breach cost millions.
- ✓Use OIDC federation for CI/CD cloud access (short-lived tokens) rather than long-lived access keys stored as CI secrets — keys rotate automatically and cannot be leaked or reused.
- ✓OPA/Gatekeeper and Falco provide Kubernetes admission control and runtime security respectively — enforce policies at deploy time and detect anomalies at runtime.
- ✓DevSecOps succeeds when developers feel that security tools help them, not block them — invest in fast gates, low FP rates, and clear remediation guidance.
Module 36 demystifies the compliance landscape: SOC 2, PCI-DSS, HIPAA, ISO 27001, GDPR, and NIST frameworks. You will learn what each framework requires, how they overlap, how to build a unified control library that satisfies multiple frameworks simultaneously, and how to prepare for and survive an audit.
Discussion
0Have a better approach? Found something outdated? Share it — your knowledge helps everyone learning here.