Secure Development Lifecycle
When to Use
Integrate security into every phase of software development — from requirements gathering to deployment and maintenance. Security is not a gate at the end; it's woven throughout the entire process.
Decision
| Development Phase | Security Activity | Tools/Methods |
|---|---|---|
| Requirements | Threat modeling, security requirements | STRIDE, abuse cases |
| Design | Security architecture review, secure design patterns | Threat modeling, design review |
| Development | Secure coding, code review | SAST tools, peer review |
| Testing | Security testing, penetration testing | DAST tools, fuzzing |
| Deployment | Security configuration, secrets management | IaC scanning, vault |
| Maintenance | Vulnerability patching, security monitoring | Dependency scanning, SIEM |
Threat Modeling (STRIDE)
| Threat Type | Description | Example | Mitigation |
|---|---|---|---|
| Spoofing | Impersonating user/service | Stolen credentials | MFA, certificate-based auth |
| Tampering | Modifying data/code | SQL injection, MITM | Input validation, HTTPS, integrity checks |
| Repudiation | Denying actions | "I didn't send that" | Audit logs, digital signatures |
| Information Disclosure | Exposing sensitive data | SQL injection leaks data | Encryption, access control |
| Denial of Service | Making system unavailable | Resource exhaustion | Rate limiting, auto-scaling |
| Elevation of Privilege | Gaining unauthorized access | Privilege escalation bugs | Least privilege, permission checks |
Threat modeling process:
1. Diagram the system (DFD, trust boundaries, entry points)
2. Identify threats (STRIDE per component and data flow)
3. Rank by risk (Likelihood x Impact, DREAD scoring)
4. Mitigate (design controls, document decisions)
5. Validate (security testing, penetration testing)
Static Application Security Testing (SAST)
# GitHub Actions - CodeQL SAST
name: Security Scan
on: [push, pull_request]
jobs:
codeql:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: github/codeql-action/init@v2
with:
languages: javascript, python
- uses: github/codeql-action/analyze@v2
SAST tools by language:
| Language | Tools |
|---|---|
| JavaScript/TypeScript | ESLint security plugins, Semgrep, SonarQube |
| Python | Bandit, Semgrep, PyLint security |
| PHP | RIPS, Psalm, Phan |
| Java | SpotBugs, Checkmarx, SonarQube |
| Go | Gosec, StaticCheck |
Dynamic Application Security Testing (DAST)
# OWASP ZAP scan in CI/CD
- name: ZAP Baseline Scan
uses: zaproxy/action-baseline@v0.7.0
with:
target: 'https://staging.example.com'
DAST vs SAST:
- SAST: Analyzes source code, finds potential vulnerabilities early, many false positives
- DAST: Tests running app, finds runtime issues, fewer false positives but slower
Security Code Review Checklist
[ ] Input Validation - allowlist, type checking, length limits
[ ] Output Encoding - context-specific escaping, auto-escaping enabled
[ ] Authentication/Authorization - checks on every request, secure sessions
[ ] Cryptography - strong algorithms, no hardcoded keys, secure random
[ ] Error Handling - no sensitive data in errors, fail securely
[ ] Dependencies - no known vulnerabilities, locked versions
[ ] Logging - security events logged, no sensitive data in logs
[ ] API Security - rate limiting, CORS configured, auth required
Penetration Testing
| Type | Tester Knowledge | Use Case |
|---|---|---|
| Black Box | No knowledge of system | Simulates external attacker |
| White Box | Full knowledge (source code) | Comprehensive testing |
| Gray Box | Partial knowledge | Most common, balanced |
When to perform: Before major releases, after architecture changes, annually, after security incidents.
Secure CI/CD Pipeline
name: Secure Pipeline
on: [push, pull_request]
jobs:
security-scan:
steps:
# 1. Secret scanning
- uses: trufflesecurity/trufflehog@main
# 2. Dependency scanning
- run: npm audit --audit-level=high
# 3. SAST
- uses: github/codeql-action/analyze@v2
# 4. Container scanning
- uses: aquasecurity/trivy-action@master
with:
image-ref: 'myapp:latest'
severity: 'CRITICAL,HIGH'
# 5. IaC scanning
- uses: aquasecurity/tfsec-action@v1.0.0
# 6. DAST (on staging)
- uses: zaproxy/action-baseline@v0.7.0
Secrets Management
# Bad: Secrets in code
API_KEY = "sk_live_abc123" # NEVER
# Good: Secrets in vault (HashiCorp Vault, AWS Secrets Manager)
import hvac
client = hvac.Client(url='http://127.0.0.1:8200', token=os.environ['VAULT_TOKEN'])
db_password = client.secrets.kv.v2.read_secret_version(path='database')['data']['data']['password']
Common Mistakes
- Security as afterthought — "We'll add security later" never works. Retrofitting costs 100x more
- No threat modeling — Building without understanding threats = vulnerabilities by design
- Ignoring SAST/DAST findings — Triage, don't ignore
- Security gates block releases — Integrate security into CI/CD, don't bolt it on at the end
- No security training — Developers can't write secure code without training
- Secrets in version control — Use
.gitignore, secret scanning (TruffleHog, git-secrets) - Not patching quickly — Patch critical issues within 48 hours
- No bug bounty program — External researchers find vulnerabilities. Use HackerOne/Bugcrowd
See Also
- Previous: Cryptography Basics | Next: Common Security Anti-Patterns
- Reference: OWASP SAMM
- Reference: Microsoft Security Development Lifecycle