Master core concepts and production patterns.
In 2021, the SolarWinds breach compromised thousands of organizations after malicious code was inserted into a software build pipeline, and attackers had months of access before anyone noticed. A DevSecOps pipeline with automated security gates would have caught anomalies far earlier. **DevSecOps** moves security checks left — into the development pipeline, before code ever reaches production. Every pull request gets scanned: containers are checked for known vulnerabilities, infrastructure code is checked for misconfigurations, and dependency trees are checked for packages with known CVEs. If a critical finding is detected, the pipeline fails, the code does not deploy, and the developer gets a clear report explaining exactly what to fix. [ Developer opens a Pull Request ] | v [ GitHub Actions triggers ] | v [ Gate 1: Unit tests must pass ] | v [ Gate 2: Trivy scans image for CVEs ] | v [ Gate 3: Checkov scans Terraform ] | v [ Gate 4: Snyk scans dependencies ] | v [ Gate 5: Gitleaks scans for secrets ] | +-------+-------+ | | All gates pass Any gate fails | | v v [ Deploy ] [ PR blocked with report ] At companies like Razorpay, where a single leaked API key or unencrypted S3 bucket carries direct financial and compliance risk, this exact pattern — scan on every PR, block on critical findings — is table stakes for the platform team. > 💡 **Tip:** This is one of the most directly employable skills in this project catalog — most serious engineering teams in 2026 expect their CI/CD pipeline to already have security gates built in, not bolted on later.
Without automated scanning, a team can unknowingly ship a container built on a base image with a known remote-code-execution vulnerability, or Terraform that leaves an S3 bucket world-readable, or a `requirements.txt` pinned to a Flask version with a known XSS flaw. None of these get caught until a scanner — or an attacker — finds them. This project solves that by putting real, automated checks directly in the pull request path. A **CVE** (Common Vulnerabilities and Exposures) is a publicly known security flaw, scored from CRITICAL down to LOW. Scanning tools compare what you're about to ship against databases of known CVEs and known-bad infrastructure patterns, and the pipeline can be configured to physically block a merge when something CRITICAL is found — not just log a warning nobody reads. **Trivy** (by Aqua Security) scans containers, filesystems, and repos for CVEs. **Checkov** statically analyzes Infrastructure as Code — Terraform, CloudFormation, Kubernetes YAML — against hundreds of security rules. **Snyk** scans your dependency tree for vulnerable packages. Together with a secret scanner (Gitleaks), they cover the four places vulnerabilities most commonly hide: the container, the infrastructure code, the dependency tree, and the Git history itself. > ⚠️ **Security:** A security gate that only reports findings without ever blocking a merge is not a gate — it's a dashboard. That distinction is the core lesson of this project. ---
Master core concepts and production patterns.
We'll intentionally plant a few real misconfigurations in this milestone's Terraform — this isn't sloppiness, it's so you can watch the scanners actually catch something real in Milestone 2, instead of trusting a green pipeline you've never seen turn red.
```bash mkdir devsecops-project cd devsecops-project cat > app.py << 'EOF' from flask import Flask, jsonify app = Flask(__name__) @app.route('/health') def health(): return jsonify({'status': 'ok'}), 200 @app.route('/api/orders') def orders(): return jsonify({ 'orders': [ {'id': 'ORD-001', 'status': 'delivered', 'amount': 450}, {'id': 'ORD-002', 'status': 'processing', 'amount': 230} ] }) if __name__ == '__main__': app.run(host='0.0.0.0', port=8080) EOF cat > requirements.txt << 'EOF' flask==3.0.3 gunicorn==21.2.0 pytest==8.2.0 EOF cat > Dockerfile << 'EOF' FROM python:3.12-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY app.py . RUN groupadd -r appgroup && \ useradd -r -g appgroup appuser RUN chown -R appuser:appgroup /app USER appuser EXPOSE 8080 CMD ["gunicorn", "--bind", "0.0.0.0:8080", "--workers", "2", "app:app"] EOF ``` Create a Terraform file with a few intentional misconfigurations, modeled on an S3 logging bucket like the ones Swiggy's platform team would provision for order-event logs: ```bash mkdir terraform cat > terraform/main.tf << 'EOF' ## S3 bucket for application logs resource "aws_s3_bucket" "logs" { bucket = "devops-network-app-logs-2026" } ## No server-side encryption enabled - Checkov catches this as CKV_AWS_19 ## No bucket versioning enabled - Checkov catches this as CKV_AWS_52 resource "aws_security_group" "app" { name = "app-security-group" vpc_id = "vpc-12345678" ## SSH open to the entire internet - Checkov catches this as CKV_AWS_25 ingress { from_port = 22 to_port = 22 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } } EOF ``` > 🔴 **Common Mistake:** Running the container as root because it's "just a local test." Even for practice projects, build the habit of a dedicated non-root user from the first Dockerfile you write — retrofitting it later on a real production image is far more disruptive. ---
Master this concept and view production exercises.
In 2021, the SolarWinds breach compromised thousands of organizations after malicious code was inserted into a software ...
Without automated scanning, a team can unknowingly ship a container built on a base image with a known remote-code-execu...
Master this concept and view production exercises.
We'll intentionally plant a few real misconfigurations in this milestone's Terraform — this isn't sloppiness, it's so yo...
Create a Terraform file with a few intentional misconfigurations, modeled on an S3 logging bucket like the ones Swiggy's...
Master this concept and view production exercises.
Running scanners locally before they ever touch CI does two things: it lets you fix obvious issues fast without waiting ...
Scan the built image: Scan the Terraform: Checkov found exactly the three issues planted in Milestone 1 — now you know p...
Master this concept and view production exercises.
The pipeline below deliberately splits each scanner into two steps: one that reports (uploads a SARIF file to GitHub's S...
> 🔴 Common Mistake: Using --exit-code 0 for every Trivy step means findings get logged but never block anything. The pa...
Master this concept and view production exercises.
Each fix below maps directly to one Checkov rule ID from Milestone 2. Reading the rule ID alongside the fix is a habit w...
> ⚠️ Security: Even the fixed security group still allows SSH from the entire VPC CIDR (10.0.0.0/8), not just a specific...
Master this concept and view production exercises.
Uploading SARIF results to the Security tab is useful, but most engineers live in the pull request, not the Security tab...
> 💡 Tip: Extend this same pattern to the Snyk and Gitleaks jobs once you're comfortable with it — a single comment summ...
Master this concept and view production exercises.
> 💡 Tip: Deliberately reintroduce one of the fixed misconfigurations in a test branch and open a PR — watching the pipe...
Mistake Why It Breaks Fix --exit-code 0 everywhere Findings logged but never block Use exit-code 1 in the enforcement st...
Aligns directly with DevOps, Site Reliability (SRE), and Platform Engineering job descriptions.