Secure Development Lifecycle (SDL)

Integrate security into every phase of software development — threat modeling with STRIDE, SAST/DAST automation, dependency scanning, secrets management, and DevSecOps pipeline security.

Medium 60m 3 tasks

Learning Objectives

  • Apply STRIDE threat modeling to identify security requirements
  • Configure SAST tools (Semgrep, Bandit) in CI/CD pipelines
  • Use DAST tools (OWASP ZAP) for automated web security testing
  • Scan dependencies for known CVEs with SBOM and Dependabot
  • Implement secrets management to eliminate hardcoded credentials

The Cost of Security

Security cost by phase (relative):
Design phase:      $1    (fix a design flaw in architecture)
Development:       $6    (refactor the code)
Testing:           $15   (fix after QA finds it)
Production:        $100+ (breach, reputation damage, legal)

"Shift Left": move security earlier in development
Goal: find and fix security issues at design/code time, not after breach

SDL Phases:
1. Requirements — security requirements from compliance, risk assessment
2. Design — threat modeling, attack surface analysis
3. Implementation — secure coding, SAST, code review
4. Verification — DAST, penetration test, fuzzing
5. Release — final security review, SDL checklist
6. Response — IR plan, patch management, bug bounty

STRIDE Threat Modeling

STRIDE: Microsoft's threat classification framework
Applied per component: "what threats exist to THIS element?"

S  Spoofing Identity
    Threat: attacker impersonates a user or service
    Defense: authentication (MFA, certificates, OAuth)

T  Tampering with Data
    Threat: attacker modifies data in transit or at rest
    Defense: integrity checks (HMAC, digital signatures, TLS)

R  Repudiation
    Threat: user denies performing an action
    Defense: audit logging, non-repudiation (digital signatures)

I  Information Disclosure
    Threat: unauthorized access to sensitive data
    Defense: encryption, access control, data minimization

D  Denial of Service
    Threat: legitimate users can't access service
    Defense: rate limiting, input validation, WAF, CDN

E  Elevation of Privilege
    Threat: normal user gains admin/system access
    Defense: least privilege, authorization checks, input validation

Threat modeling process:
1. Decompose: identify components, data flows, trust boundaries
2. Enumerate: for each component, apply STRIDE
3. Rate: DREAD or CVSS for each threat
4. Mitigate: identify controls, verify they address the threat

Tools: Microsoft Threat Modeling Tool (free), OWASP Threat Dragon

SAST (Static Application Security Testing)

# SAST: analyze source code without executing it
# Finds: SQL injection, XSS, hardcoded secrets, insecure functions

# Semgrep: fast, pattern-based, multi-language SAST
pip3 install semgrep

# Run against a project:
semgrep --config auto ./src/         # community rules
semgrep --config p/python-security ./src/  # Python-specific rules
semgrep --config p/owasp-top-10 ./src/

# Custom rule example:
cat > no_eval.yaml << 'EOF'
rules:
  - id: no-eval
    patterns:
      - pattern: eval(...)
    message: "Dangerous use of eval() — code injection risk"
    severity: ERROR
    languages: [javascript, python]
EOF
semgrep --config no_eval.yaml ./src/

# Bandit: Python-specific SAST
pip3 install bandit
bandit -r ./src/ -ll  # low level issues and above
bandit -r ./src/ -f json -o results.json

# ESLint with security plugins:
npm install eslint-plugin-security
# Finds: NoSQL injection, path traversal, eval(), Buffer vulnerabilities

# CodeQL (GitHub): semantic code analysis
# GitHub Actions:
- name: Initialize CodeQL
  uses: github/codeql-action/init@v2
  with: languages: 'python, javascript'
- name: Analyze
  uses: github/codeql-action/analyze@v2

DAST (Dynamic Application Security Testing)

# DAST: test running application — finds what SAST misses
# Interaction-based: actually sends HTTP requests, observes responses

# OWASP ZAP (Zed Attack Proxy):
# GUI: run ZAP, configure browser proxy, browse app, Active Scan
# CLI:
docker run -t owasp/zap2docker-stable zap-baseline.py -t https://TARGET_URL

# ZAP in CI/CD (GitHub Actions):
- name: ZAP Scan
  uses: zaproxy/[email protected]
  with:
    target: 'https://staging.myapp.com'
    rules_file_name: '.zap/rules.tsv'

# Nuclei: fast vulnerability scanner with community templates
go install github.com/projectdiscovery/nuclei/v2/cmd/nuclei@latest
nuclei -u https://target.com -t cves/       # CVE checks
nuclei -u https://target.com -t exposures/  # exposed endpoints
nuclei -u https://target.com -severity critical,high

# Burp Suite Pro: automated scanner + manual
# Configure in CI: Burp Scan via API

Dependency Scanning & SBOM

# Dependencies often have more vulnerabilities than your own code!
# npm, pip, maven packages can have critical CVEs

# SBOM (Software Bill of Materials): list of all dependencies
# Required by US Executive Order 14028 (federal software)

# Python: pip-audit
pip install pip-audit
pip-audit
# Output: found 5 vulnerabilities in 2 packages (CVE-2023-xxxx)

# JavaScript: npm audit
npm audit
npm audit fix  # auto-fix safe updates
npm audit fix --force  # force update (may break APIs)

# Snyk: comprehensive SAST + dependency scanning
npm install -g snyk
snyk auth
snyk test  # scan dependencies for CVEs
snyk code test  # SAST scan

# GitHub Dependabot: automatic PRs for vulnerable dependencies
# .github/dependabot.yml:
version: 2
updates:
  - package-ecosystem: "pip"
    directory: "/"
    schedule:
      interval: "weekly"
    security-updates-only: true

# SBOM generation:
# Syft: generates SBOM in SPDX, CycloneDX formats
syft dir:. -o cyclonedx-json=sbom.json

# Grype: vulnerability scanner using SBOM
grype sbom:sbom.json

Secrets Management

# Never hardcode secrets in code!
# .env files should never be committed to git

# Git pre-commit hook to prevent secrets:
pip3 install pre-commit
pip3 install detect-secrets

# .pre-commit-config.yaml:
repos:
  - repo: https://github.com/Yelp/detect-secrets
    rev: v1.4.0
    hooks:
      - id: detect-secrets

pre-commit install  # installs hooks
# Now: git commit fails if secrets detected

# Scan git history for already-committed secrets:
trufflehog git file://. --only-verified
# or: git-secrets --scan-history

# Secret managers:
# HashiCorp Vault: centralized secret storage with dynamic credentials
vault kv put secret/app/db password=SuperSecret123
vault kv get secret/app/db
# Application reads at runtime, not from config file

# AWS Secrets Manager:
aws secretsmanager get-secret-value --secret-id prod/db/password

# Environment variables (minimal viable approach):
import os
DB_PASSWORD = os.environ['DB_PASSWORD']  # GOOD
# DB_PASSWORD = 'hardcoded'  # BAD

# 12-factor app: config from environment

DevSecOps Pipeline

# Complete DevSecOps GitHub Actions pipeline:
name: Security Pipeline
on: [push, pull_request]

jobs:
  sast:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Semgrep SAST
        uses: returntocorp/semgrep-action@v1
        with: config: p/owasp-top-10

  dependency-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: pip-audit
        run: pip install pip-audit && pip-audit -r requirements.txt
      - name: npm audit
        run: npm audit --audit-level=high

  secrets-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
        with: fetch-depth: 0  # full history for trufflehog
      - name: TruffleHog
        uses: trufflesecurity/trufflehog@main
        with: only-verified: true

  container-scan:
    runs-on: ubuntu-latest
    steps:
      - name: Build image
        run: docker build -t myapp:latest .
      - name: Trivy scan
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: myapp:latest
          exit-code: 1
          severity: CRITICAL

Threat model the CyberLearn platform (or your own app): (1) draw a data flow diagram: browser, web server, database, cache, auth service, (2) identify trust boundaries: internet-to-server, server-to-DB, (3) apply STRIDE to each component — for the login endpoint: S=credential stuffing, T=session token tampering, R=no audit log, I=password in URL logs, D=no rate limiting, E=IDOR to other users, (4) rate each threat with CVSS, (5) propose mitigations for each — map to OWASP controls.

✦ Answer the questions to complete this task

What is a trust boundary in threat modeling?

Integrate SAST into a Python project: (1) install Bandit: pip3 install bandit, (2) run: bandit -r . -ll (list medium+ issues), (3) introduce an intentional vulnerability: cursor.execute('SELECT * FROM users WHERE id=' + user_id) — SQL injection, (4) re-run Bandit: it should flag the SQL injection, (5) set up a pre-commit hook: pip3 install pre-commit, add bandit to .pre-commit-config.yaml, (6) commit the vulnerable code — the hook should block it.

✦ Answer the questions to complete this task

What is the difference between SAST false positives and false negatives?

Audit dependencies for CVEs: (1) pip-audit your project's requirements.txt, (2) npm audit an old JavaScript project (create package.json with outdated packages: [email protected], [email protected]), (3) identify critical/high CVEs in the old packages, (4) generate an SBOM with Syft, (5) scan SBOM with Grype, (6) update vulnerable packages and re-scan, (7) set up Dependabot in a GitHub repository.

✦ Answer the questions to complete this task

What is an SBOM and why is it required by US Executive Order 14028?

💪 Exercises & Challenges

📝 MCQ Medium +20 XP

SDL MCQ

SDL MCQ

Start →
⚙️ Practical Medium +30 XP

DevSecOps Pipeline Setup

DevSecOps Pipeline Setup

Start →
🚩 Challenge Hard +50 XP

Identify the SDL Failure

Identify the SDL Failure

Start →