Why This Matters#

Most vulnerabilities are introduced during development. Fixing a vulnerability in production costs 30–100x more than fixing it during design. Secure development integrates security into every phase of the SDLC — shifting left means finding and fixing issues earlier, when they’re cheapest.


Secure SDLC#

flowchart LR
    Req["Requirements<br/>· Security Requirements<br/>· Abuse Cases"] --> Design["Design<br/>· Threat Model<br/>· Architecture Review"]
    Design --> Code["Code<br/>· Secure Coding<br/>· SAST + SCA"]
    Code --> Test["Test<br/>· DAST + Pentest<br/>· Fuzz Testing"]
    Test --> Deploy["Deploy<br/>· Config Review<br/>· Secrets Check"]
    Deploy --> Operate["Operate<br/>· Monitor<br/>· Respond + Patch"]

Security Activities per Phase#

PhaseSecurity ActivitiesOutput
RequirementsSecurity requirements, abuse cases, compliance needsSecurity user stories
DesignThreat modeling, architecture review, crypto designThreat model document
ImplementationSecure coding standards, SAST, code reviewClean code, no critical findings
TestingDAST, penetration testing, fuzz testingSecurity test report
DeploymentConfiguration review, secrets scanning, hardeningSecure deployment
OperationsMonitoring, vulnerability management, incident responseOngoing security posture

Threat Modeling#

STRIDE Model#

Systematic identification of threats per component:

ThreatAgainstQuestionMitigation
SpoofingAuthenticationCan someone pretend to be another user?Strong auth, MFA
TamperingIntegrityCan data be modified in transit/at rest?Signatures, checksums, TLS
RepudiationNon-repudiationCan someone deny their actions?Audit logs, digital signatures
Information DisclosureConfidentialityCan data be exposed?Encryption, access controls
Denial of ServiceAvailabilityCan the system be made unavailable?Rate limiting, scaling, redundancy
Elevation of PrivilegeAuthorizationCan someone gain unauthorized access?Least privilege, input validation

Threat Modeling Process#

flowchart TD
    Scope["1: Define Scope<br/>(what are we modeling?)"]
    Scope --> Diagram["2: Create Data Flow Diagram<br/>(components, data flows, trust boundaries)"]
    Diagram --> Identify["3: Identify Threats<br/>(STRIDE per element)"]
    Identify --> Mitigate["4: Define Mitigations<br/>(controls per threat)"]
    Mitigate --> Validate["5: Validate<br/>(are mitigations implemented?)"]

Data Flow Diagram Elements#

ElementSymbolExample
ProcessCircleWeb server, API service
Data StoreParallel linesDatabase, file system
External EntityRectangleUser, third-party API
Data FlowArrowHTTP request, DB query
Trust BoundaryDashed lineInternet/DMZ, DMZ/internal

Secure Coding Practices#

Input Validation#

RuleImplementation
Validate all inputServer-side validation (never trust client)
Allowlist over denylistDefine what’s valid, reject everything else
Validate type, length, rangeReject before processing
Canonicalize before validationDecode, normalize, then validate
Reject on failureDon’t try to “fix” bad input

Output Encoding#

ContextEncodingPrevents
HTML bodyHTML entity encodingXSS
HTML attributeAttribute encodingXSS
JavaScriptJavaScript encodingXSS
URL parameterURL encodingInjection
SQLParameterized queriesSQL injection
OS commandAvoid entirely; use APIsCommand injection

Authentication & Session#

PracticeImplementation
Hash passwords properlyArgon2id or bcrypt (never MD5/SHA)
Enforce password complexityMinimum length (12+), check against breached lists
Implement account lockoutTemporary lockout after N failures
Secure session tokensCryptographically random, sufficient length
Set cookie flagsSecure; HttpOnly; SameSite=Strict
Implement proper logoutInvalidate server-side session

Error Handling#

DoDon’t
Log detailed errors server-sideExpose stack traces to users
Return generic error messagesReveal internal paths or versions
Use structured error codesLeak database schema in errors
Fail securely (deny access on error)Fail open (grant access on error)

Security Testing#

SAST (Static Application Security Testing)#

Analyzes source code without executing it:

ToolLanguagesIntegration
SonarQube30+ languagesCI/CD, IDE
Semgrep30+ languagesCI/CD, pre-commit
CodeQLMajor languagesGitHub Actions
CheckmarxEnterpriseCI/CD
BanditPythonCI/CD, pre-commit

Strengths: Finds code-level flaws early, covers all code paths. Weaknesses: High false positive rate, no runtime context.

DAST (Dynamic Application Security Testing)#

Tests the running application from outside:

ToolTypeUse Case
OWASP ZAPOpen sourceCI/CD integration, API testing
Burp SuiteCommercialManual + automated testing
NucleiOpen sourceTemplate-based scanning

Strengths: Finds runtime issues, low false positives. Weaknesses: Only tests reachable code paths, slower.

SCA (Software Composition Analysis)#

Identifies vulnerable dependencies:

ToolCoverageFeatures
SnykMulti-languageFix PRs, license compliance
DependabotGitHub nativeAuto-update PRs
TrivyContainers + codeFast, comprehensive
OWASP Dependency-CheckJava, .NETFree, CI/CD
RenovateMulti-platformConfigurable auto-updates

Fuzz Testing#

Sends random/malformed input to find crashes and unexpected behavior:

TypeMethodFinds
Dumb fuzzingRandom mutationsBuffer overflows, crashes
Smart fuzzingGrammar-aware mutationsLogic errors, parsing bugs
Coverage-guidedMaximize code coverageDeep bugs in complex code

Supply Chain Security#

Attack Vectors#

flowchart TD
    SC["Supply Chain Attacks"]
    SC --> Dep["Dependency Attacks"]
    SC --> Build["Build Pipeline Attacks"]
    SC --> Dist["Distribution Attacks"]
    
    Dep --> Typo["Typosquatting<br/>(lodash → lodahs)"]
    Dep --> Takeover["Maintainer Takeover<br/>(compromised npm account)"]
    Dep --> Malicious["Malicious Update<br/>(event-stream incident)"]
    
    Build --> CI["CI/CD Compromise<br/>(stolen secrets)"]
    Build --> Inject["Build Injection<br/>(SolarWinds)"]
    
    Dist --> Tamper["Package Tampering<br/>(modified binary)"]
    Dist --> Mirror["Compromised Mirror<br/>(fake repository)"]

Defenses#

DefenseMechanism
Lock filesPin exact versions (package-lock.json, Pipfile.lock)
Integrity verificationCheck hashes/signatures of packages
Private registryMirror approved packages internally
SBOM generationKnow exactly what’s in your software
Dependency reviewReview new dependencies before adding
Automated updatesRenovate/Dependabot with CI gates
SLSA frameworkSupply chain integrity levels

SLSA (Supply-chain Levels for Software Artifacts)#

LevelRequirements
SLSA 1Build process documented
SLSA 2Hosted build service, authenticated provenance
SLSA 3Hardened build platform, non-falsifiable provenance
SLSA 4Two-person review, hermetic builds

Secrets Management in Code#

What NOT to Do#

# NEVER commit these:
API_KEY=sk-abc123def456
DATABASE_URL=postgres://admin:password@prod-db:5432/app
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

Secrets Detection#

ToolIntegrationFeatures
git-secretsPre-commit hookAWS-focused patterns
truffleHogCI/CD, pre-commitEntropy + regex detection
GitleaksCI/CD, pre-commitFast, configurable rules
GitHub Secret ScanningGitHub nativeAlerts on pushed secrets

Secrets Management Solutions#

SolutionUse Case
AWS Secrets ManagerApplication secrets, auto-rotation
HashiCorp VaultMulti-cloud, dynamic secrets
Environment variablesSimple deployments (with caution)
CI/CD variablesPipeline secrets (masked, protected)

Security in CI/CD Pipeline#

flowchart LR
    Commit["Commit"] --> Secrets["Secrets<br/>Scan"]
    Secrets --> SAST["SAST"]
    SAST --> SCA["SCA<br/>(dependencies)"]
    SCA --> Build["Build"]
    Build --> Image["Container<br/>Scan"]
    Image --> DAST["DAST<br/>(staging)"]
    DAST --> Gate{"Security<br/>Gate"}
    Gate -->|Pass| Deploy["Deploy"]
    Gate -->|Fail| Block["Block +<br/>Notify"]

Security Gates#

GateBlocks OnRationale
Secrets scanAny detected secretPrevents credential leaks
SASTCritical/High findingsPrevents code-level vulnerabilities
SCACritical CVEs, license violationsPrevents known vulnerable dependencies
Container scanCritical CVEs in base imagePrevents deploying vulnerable containers
DASTCritical findingsPrevents runtime vulnerabilities

Key Takeaways#

  1. Shift left — security in requirements and design, not just testing
  2. Threat model every significant feature — STRIDE gives structure
  3. Automate in CI/CD — SAST, SCA, secrets scanning on every commit
  4. Supply chain is a real threat — lock versions, verify integrity, use SBOM
  5. Never commit secrets — use pre-commit hooks + secrets managers
  6. Security gates prevent deployment of known-bad code — block on critical
  7. Defense in depth applies to code too — validate input, encode output, fail securely