Building secure software requires integrating security at every stage of development, not bolting it on at the end. This guide covers practical approaches to implementing a secure software development lifecycle (SSDLC) that balances security with development velocity.
The Cost of Late-Stage Security
Security issues found in production cost 30-100x more to fix than those found during design. Beyond direct costs:
- Emergency patches disrupt planned work
- Breaches damage reputation and customer trust
- Regulatory penalties for insecure software are increasing
- Technical debt compounds over time
Shifting security left reduces costs and improves outcomes.
Phase 1: Requirements and Design
Security Requirements
Identify security requirements alongside functional requirements:
Regulatory Requirements
- PCI DSS for payment processing
- HIPAA for health information
- GDPR/CCPA for personal data
- SOX for financial systems
Security Stories Write security requirements as user stories:
- “As a user, I want my password stored securely so that it cannot be stolen if the database is breached”
- “As an admin, I want to see audit logs of all user actions so that I can investigate incidents”
Threat Modeling
Identify threats before writing code:
STRIDE Model
- Spoofing: Can attackers impersonate users or systems?
- Tampering: Can data be modified inappropriately?
- Repudiation: Can users deny actions they performed?
- Information disclosure: Can sensitive data leak?
- Denial of service: Can the system be made unavailable?
- Elevation of privilege: Can users gain unauthorized access?
Practical Approach
- Draw data flow diagrams
- Identify trust boundaries
- Enumerate threats using STRIDE
- Prioritize by risk (likelihood × impact)
- Define mitigations
- Track in issue tracker
Secure Architecture Patterns
Apply proven patterns:
- Defense in depth: Multiple layers of controls
- Least privilege: Minimal permissions by default
- Fail secure: Safe defaults when errors occur
- Separation of concerns: Isolate sensitive functionality
- Input validation: Validate all input at boundaries
Phase 2: Development
Secure Coding Standards
Establish language-specific standards:
OWASP Guidelines
- Input validation and output encoding
- Authentication and session management
- Access control
- Cryptographic practices
- Error handling and logging
Language-Specific Resources
- Java: CERT Oracle Secure Coding Standard
- C/C++: SEI CERT C Coding Standard
- Python: OWASP Python Security
- JavaScript: Node.js Security Best Practices
IDE Security Plugins
Catch issues while coding:
- SonarLint for multi-language analysis
- Snyk for dependency vulnerabilities
- GitLens for commit security
- ESLint security rules for JavaScript
Dependency Management
Control third-party risk:
# Example GitHub Actions dependency scanning
name: Dependency Review
on: [pull_request]
jobs:
dependency-review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/dependency-review-action@v4
with:
fail-on-severity: moderate
Best Practices
- Pin dependency versions
- Use lock files (package-lock.json, Pipfile.lock)
- Automate vulnerability scanning in CI
- Have a process for updating vulnerable dependencies
Secrets Management
Never hardcode secrets:
Do
- Use environment variables for configuration
- Use secrets management services (HashiCorp Vault, AWS Secrets Manager)
- Rotate secrets regularly
- Use pre-commit hooks to detect secrets
Don’t
- Commit secrets to version control
- Log secrets or sensitive data
- Share secrets via email or chat
- Use the same secrets across environments
Phase 3: Testing
Static Application Security Testing (SAST)
Analyze code without executing:
Tools
- SonarQube / SonarCloud
- Checkmarx
- Fortify
- Semgrep
Integration Points
- IDE plugins for immediate feedback
- Pre-commit hooks for blocking commits
- CI/CD pipeline for PR review
- Scheduled scans of main branches
Dynamic Application Security Testing (DAST)
Test running applications:
Tools
- OWASP ZAP
- Burp Suite
- Invicti (formerly Netsparker)
- Qualys WAS
Integration Points
- Scan staging environments after deployment
- Include in regression test suite
- Schedule regular scans of production
Software Composition Analysis (SCA)
Identify vulnerable dependencies:
Tools
- Snyk
- Dependabot
- OWASP Dependency-Check
- Black Duck
Penetration Testing
Manual security testing:
- Conduct annually at minimum
- Test after major changes
- Use qualified testers (OSCP, CREST certified)
- Address findings before release
Phase 4: Deployment
Secure CI/CD Pipelines
Protect the build process:
# Example secure GitHub Actions workflow
name: Secure Build
on: [push]
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@v4
- name: Run SAST
uses: github/codeql-action/analyze@v2
- name: Scan dependencies
uses: snyk/actions/node@master
- name: Build with minimal permissions
run: npm ci && npm run build
- name: Sign artifacts
uses: sigstore/cosign-action@v3
Pipeline Security Checklist
- Minimize pipeline permissions
- Sign build artifacts
- Scan container images
- Verify dependencies integrity
- Protect secrets with OIDC
Infrastructure as Code Security
Secure infrastructure configurations:
- Scan Terraform/CloudFormation before apply
- Use policy as code (OPA, Sentinel)
- Version control all infrastructure
- Review infrastructure changes like code
Phase 5: Operations
Security Monitoring
Detect issues in production:
- Application logging (security events)
- Runtime Application Self-Protection (RASP)
- Web Application Firewall (WAF)
- API security monitoring
Vulnerability Management
Handle discovered issues:
- Triage: Assess severity and exploitability
- Prioritize: Based on risk and exposure
- Remediate: Fix or mitigate
- Verify: Confirm fix is effective
- Track: Measure metrics over time
Incident Response
Prepare for security incidents:
- Document response procedures
- Define severity levels and SLAs
- Establish communication channels
- Practice with tabletop exercises
Metrics
Measure SSDLC effectiveness:
- Mean time to remediate: How quickly are vulnerabilities fixed?
- Vulnerability density: Issues per lines of code
- Escape rate: Vulnerabilities found in production vs. development
- Fix rate: Percentage of findings addressed
- Coverage: Percentage of code/applications scanned