Security by Design: From Legal Requirement to Engineering Practice
The CRA mandates βsecurity by design and by default.β But what does that actually mean in daily engineering work? Here are the concrete practices that satisfy this requirement.
Threat Modeling
Every product must have a documented threat model:
# STRIDE threat model for a web application
threats = {
"Spoofing": [
"Attacker impersonates legitimate user via stolen credentials",
"Mitigation: MFA, session management, credential rotation",
],
"Tampering": [
"Attacker modifies API requests in transit",
"Mitigation: TLS everywhere, request signing, integrity checks",
],
"Repudiation": [
"User denies performing an action",
"Mitigation: Immutable audit logs, request logging",
],
"Information Disclosure": [
"Sensitive data exposed through error messages or logs",
"Mitigation: Error sanitization, log redaction, encryption at rest",
],
"Denial of Service": [
"Attacker overwhelms service with requests",
"Mitigation: Rate limiting, autoscaling, circuit breakers",
],
"Elevation of Privilege": [
"Attacker gains admin access through vulnerability",
"Mitigation: Least privilege, RBAC, input validation",
],
}Secure Defaults
Every configuration choice must default to the secure option:
# Bad: Insecure defaults
server:
tls: false # Disabled by default
auth: optional # No auth required
cors: "*" # Allow all origins
# Good: Secure defaults (CRA compliant)
server:
tls: true # Enabled by default
auth: required # Authentication mandatory
cors: [] # No origins allowed by default
headers:
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Strict-Transport-Security: max-age=31536000Automated Security Testing
# CI/CD security gates
stages:
- lint
- sast
- build
- dast
- sbom
- sign
sast:
stage: sast
script:
- semgrep --config auto --error --json > sast-results.json
dependency-check:
stage: sast
script:
- trivy fs --severity HIGH,CRITICAL --exit-code 1 .
container-scan:
stage: build
script:
- trivy image --severity HIGH,CRITICAL myapp:$CI_COMMIT_SHA
dast:
stage: dast
script:
- zap-baseline.py -t https://staging.example.com -r dast-report.html
sbom-generate:
stage: sbom
script:
- syft . -o cyclonedx-json > sbom.json
- grype sbom:sbom.json --fail-on critical
sign-artifacts:
stage: sign
script:
- cosign sign --key cosign.key myapp:$CI_COMMIT_SHA
- cosign attach sbom --sbom sbom.json myapp:$CI_COMMIT_SHAKey Practices
- Threat model before coding β document threats and mitigations for every new feature
- Default deny β no access, no connectivity, no permissions unless explicitly granted
- Automate security testing β SAST, DAST, dependency scanning in every pipeline
- Minimize attack surface β remove unused features, close unnecessary ports
- Document security decisions β CRA requires technical documentation of security rationale
Security by design isnβt a one-time activity β itβs embedded in every sprint, every PR, every deployment.
Implementing security by design for CRA compliance? I help teams build secure development processes. Get in touch.
