| name | security-by-design |
| description | Defense-in-depth security principles — OWASP Top 10 prevention, input validation, secure error handling, encryption, least privilege |
| license | MIT |
Security-by-Design Skill
Context
Applies to all code handling user input, state persistence, external assets, audio, networking, authentication, authorization, or sensitive configuration. Also applies to infrastructure config, CI/CD pipelines, and security-critical changes.
Aligned with Hack23 AB's ISMS — see
Information Security Policy and
Secure Development Policy.
Rules
- Assume Breach — design so a single failure cannot cascade; limit blast radius
- Defense in Depth — multiple independent layers (validate → sanitize → encode → CSP)
- Least Privilege — minimum permissions for tokens, workflows, actions, agents
- Fail Securely — fail-closed; generic error to users, detailed log server-side
- Never Trust Input — validate, sanitize, and encode every external value (client and server)
- Secure by Default — disable unused features; explicit opt-in for risky ones
- Encrypt Everything Sensitive — AES-256 at rest, TLS 1.3+ in transit, SHA-256+ hashing
- No Secrets in Code — env vars and
secrets.* only; rotate on exposure
- Audit Everything — log auth, authorization, security events; never log secrets/PII
- Minimize Attack Surface — remove dead features, unused endpoints, unused deps
- Test Security Controls — cover happy + failure paths (≥ 95 % coverage on security code)
- Patch Promptly — Critical ≤ 7 d, High ≤ 30 d, Medium ≤ 90 d (Vulnerability Management)
- Document Decisions — threat models, ADRs, ISMS policy citations in comments/PRs
OWASP Top 10 Quick Mapping
| OWASP 2021 | Enforcement in this project |
|---|
| A01 Broken Access Control | No client-side authorization; render-based capabilities only |
| A02 Cryptographic Failures | TLS only, no custom crypto, no plaintext storage of sensitive data |
| A03 Injection | Validate + encode; never dangerouslySetInnerHTML without DOMPurify |
| A04 Insecure Design | Threat-model per Threat Modeling Policy; STRIDE for new features |
| A05 Security Misconfiguration | Security headers (SECURITY_HEADERS.md), secure defaults |
| A06 Vulnerable Components | npm audit, Dependabot, license gate, SBOMQS ≥ 7.0 |
| A07 Identification/Auth Failures | Not applicable (no user auth in this template) — document when added |
| A08 Software/Data Integrity | SLSA L3 attestations, SHA-pinned Actions, signed releases |
| A09 Logging/Monitoring Failures | GitHub audit + Scorecard + CodeQL alerts reviewed |
| A10 SSRF | Avoid arbitrary URL fetches from untrusted input |
Compliance Controls
- ISO 27001:2022 — A.8.25 secure development, A.8.28 secure coding, A.8.29 security testing
- NIST CSF 2.0 — PROTECT (PR.DS, PR.PS, PR.IR), DETECT (DE.CM), RESPOND (RS.AN)
- CIS Controls v8.1 — 2 (software inventory), 16 (app security), 18 (pen testing)
Examples
✅ Input Validation + Encoding
function validatePlainText(input: unknown, max = 100): string {
if (typeof input !== 'string') throw new TypeError('Input must be a string');
const trimmed = input.trim();
if (trimmed.length === 0) throw new RangeError('Input is required');
if (trimmed.length > max) throw new RangeError('Input too long');
return trimmed;
}
function escapeHtml(s: string): string {
return s
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
✅ Secure Error Handling
function handleRequest(): { success?: true; error?: string } {
try {
return { success: true };
} catch {
return { error: 'An error occurred. Please try again.' };
}
}
✅ Numeric / Boundary Validation
export function saveHighScore(score: number): void {
if (!Number.isFinite(score) || score < 0 || score > 1_000_000) {
throw new RangeError('Invalid score value');
}
localStorage.setItem('highScore', String(Math.floor(score)));
}
❌ Anti-Patterns
const API_KEY = "<API_KEY>";
function handleError(e: Error) { return { error: e.stack }; }
document.body.innerHTML = userContent;
const data = JSON.parse(input) as User;
Validation Checklist