Security must be built into every phase of development, not bolted on afterward.
This skill embodies the "Security by Design" principle from Hack23 AB's ISMS framework, ensuring all code changes follow secure development practices from conception to deployment.
BEFORE writing any code that handles:
- User input
- Authentication/Authorization
- Sensitive data
- External APIs
- File operations
YOU MUST:
- Identify potential threats (STRIDE model: Spoofing, Tampering, Repudiation, Information Disclosure, Denial of Service, Elevation of Privilege)
- Assess attack surface
- Design security controls
- Document threat mitigation strategy
Example:
// ❌ BAD: Writing code without threat assessment
function processUserInput(data: string) {
return eval(data); // Critical vulnerability!
}
// ✅ GOOD: Threat-aware implementation
/**
* Process user input with security controls
* Threats mitigated:
* - Code injection: Input validation + no eval()
* - XSS: Output encoding
* - DoS: Input size limits
*/
function processUserInput(data: string): string {
// Validate input
if (typeof data !== 'string' || data.length > 1000) {
throw new Error('Invalid input');
}
// Sanitize using DOMPurify
return DOMPurify.sanitize(data);
}RULE: Never trust user input. Validate at boundaries.
Implementation:
- Use allowlists (not denylists)
- Validate type, format, length, range
- Sanitize before use
- Reject invalid input (fail secure)
// ✅ GOOD: Comprehensive input validation
import { z } from 'zod';
const SecurityLevelSchema = z.enum(['critical', 'high', 'moderate', 'low', 'public']);
function setSecurityLevel(level: unknown): SecurityLevel {
// Validate using schema
return SecurityLevelSchema.parse(level);
}RULE: Grant minimum necessary permissions.
Application:
- Limit function/component access to only required data
- Use TypeScript's
readonly,private,protected - Implement role-based access control
- Time-bound permissions where possible
// ✅ GOOD: Least privilege in action
interface UserData {
readonly id: string;
readonly email: string;
// Sensitive fields not exposed
}
function displayUser(user: Pick<UserData, 'id' | 'email'>): JSX.Element {
// Can only access id and email, nothing else
return <div>{user.email}</div>;
}RULE: Multiple layers of security controls.
Implementation:
// ✅ GOOD: Multiple security layers
async function handlePayment(data: PaymentData) {
// Layer 1: Authentication check
if (!isAuthenticated()) throw new AuthError();
// Layer 2: Authorization check
if (!hasPermission('payment:create')) throw new PermissionError();
// Layer 3: Input validation
validatePaymentData(data);
// Layer 4: Rate limiting
await checkRateLimit(userId);
// Layer 5: Encryption
const encryptedData = encrypt(data);
// Layer 6: Audit logging
await auditLog('payment:create', userId, data.amount);
return processPayment(encryptedData);
}RULE: Never expose sensitive information in errors.
// ❌ BAD: Leaking sensitive information
catch (error) {
console.log(`Database connection failed: ${dbPassword}`);
throw new Error(`SQL error: ${error.stack}`);
}
// ✅ GOOD: Secure error handling
catch (error) {
// Log detailed error securely (server-side only)
logger.error('Database operation failed', {
errorCode: error.code,
userId
});
// Return generic user-facing message
throw new Error('An error occurred. Please try again later.');
}RULE: Use proven cryptographic libraries. Never roll your own crypto.
// ❌ BAD: Custom encryption
function encrypt(data: string): string {
return btoa(data); // Not encryption!
}
// ✅ GOOD: Use proven libraries
import { webcrypto } from 'crypto';
async function encrypt(data: string, key: CryptoKey): Promise<ArrayBuffer> {
const encoder = new TextEncoder();
const dataBuffer = encoder.encode(data);
return await webcrypto.subtle.encrypt(
{ name: 'AES-GCM', iv: generateIV() },
key,
dataBuffer
);
}RULE: Minimize attack surface through dependencies.
Implementation:
- Run
npm auditbefore adding dependencies - Use GitHub Advisory Database check
- Keep dependencies updated
- Remove unused dependencies
- Pin dependency versions
# ✅ GOOD: Security checks before adding dependencies
npm audit
npm audit fix
# Check for known vulnerabilities in new package
npm view <package-name> securityRULE: Security must be tested, not assumed.
Test Categories:
- Input validation tests: Malicious inputs, edge cases
- Authentication tests: Bypass attempts, token validation
- Authorization tests: Privilege escalation, access control
- Injection tests: SQL, XSS, command injection
- Cryptography tests: Key management, encryption/decryption
// ✅ GOOD: Security-focused tests
describe('Security: Input Validation', () => {
it('should reject SQL injection attempts', () => {
const maliciousInput = "'; DROP TABLE users; --";
expect(() => validateInput(maliciousInput)).toThrow();
});
it('should reject XSS payloads', () => {
const xssPayload = '<script>alert("XSS")</script>';
expect(() => validateInput(xssPayload)).toThrow();
});
it('should enforce input length limits', () => {
const tooLong = 'a'.repeat(10001);
expect(() => validateInput(tooLong)).toThrow();
});
});- Section 4.1: Secure coding practices mandatory
- Section 4.3: Security testing in all phases
- Section 4.5: Vulnerability management
- 8.25: Secure development lifecycle
- 8.26: Application security requirements
- 8.27: Secure system architecture
- PR.DS: Data Security (protection of data at rest/transit)
- PR.IP: Information Protection Processes
- DE.CM: Security Continuous Monitoring
- Control 16: Application Software Security
- Control 18: Penetration Testing
- All user inputs MUST be validated
- Authentication/authorization MUST be tested
- Secrets MUST NOT be hardcoded
- Sensitive data MUST be encrypted
- Error messages MUST NOT leak sensitive information
- Use proven security libraries (not custom implementations)
- Implement defense in depth
- Follow principle of least privilege
- Include security test cases
- Document threat model for sensitive operations
- Use security linters (ESLint security plugins)
- Implement audit logging for sensitive operations
- Use TypeScript strict mode
- Add security-focused code comments
- Perform threat modeling workshops
When handling user input: → Validate type, format, length, range → Sanitize before use → Test with malicious payloads
When implementing authentication: → Use proven libraries (OAuth, JWT) → Implement multi-factor authentication → Test bypass scenarios
When storing data: → Encrypt sensitive data at rest → Use secure key management → Implement access controls
When communicating: → Use TLS for all connections → Validate certificates → Implement certificate pinning (mobile)
When logging: → Never log passwords, tokens, or PII → Log security events (auth failures, permission denials) → Implement log retention policies
RULE: Security must be integrated into every phase of the development lifecycle.
Security Activities:
- Threat modeling (STRIDE analysis)
- Security requirements definition
- Data classification and protection requirements
- Architecture security review
- Third-party component risk assessment
Deliverables:
// ✅ GOOD: Security requirements documented
interface SecurityRequirements {
readonly authentication: {
readonly method: 'OAuth2' | 'JWT' | 'SAML';
readonly mfaRequired: boolean;
readonly sessionTimeout: number; // seconds
};
readonly authorization: {
readonly model: 'RBAC' | 'ABAC';
readonly defaultDeny: boolean;
};
readonly dataProtection: {
readonly encryptionAtRest: boolean;
readonly encryptionInTransit: boolean;
readonly keyManagement: 'AWS_KMS' | 'Azure_KeyVault';
};
readonly auditLogging: {
readonly enabled: boolean;
readonly retentionDays: number;
};
}
const PROJECT_SECURITY_REQUIREMENTS: SecurityRequirements = {
authentication: {
method: 'OAuth2',
mfaRequired: true,
sessionTimeout: 3600,
},
authorization: {
model: 'RBAC',
defaultDeny: true,
},
dataProtection: {
encryptionAtRest: true,
encryptionInTransit: true,
keyManagement: 'AWS_KMS',
},
auditLogging: {
enabled: true,
retentionDays: 365,
},
};Reference: Secure Development Policy - Phase 1: Planning & Design
Security Activities:
- Secure coding practices (OWASP Top 10 prevention)
- Code review with security focus
- Static Application Security Testing (SAST)
- Dependency vulnerability scanning
- Secret scanning and prevention
Secure Coding Standards:
// ✅ GOOD: Secure TypeScript patterns
// 1. Input Validation
import { z } from 'zod';
const UserInputSchema = z.object({
email: z.string().email().max(254),
password: z.string().min(12).max(128),
displayName: z.string().min(1).max(100).regex(/^[a-zA-Z0-9\s]+$/),
});
function registerUser(input: unknown): Promise<User> {
// Validate input structure
const validated = UserInputSchema.parse(input);
// Additional security checks
if (await isEmailBlacklisted(validated.email)) {
throw new Error('Email not allowed');
}
// Hash password with bcrypt
const hashedPassword = await bcrypt.hash(validated.password, 12);
return createUser({
...validated,
password: hashedPassword,
});
}
// 2. SQL Injection Prevention
import { sql } from 'kysely';
// ❌ BAD: String concatenation
const badQuery = `SELECT * FROM users WHERE email = '${email}'`;
// ✅ GOOD: Parameterized queries
const users = await db
.selectFrom('users')
.selectAll()
.where('email', '=', email)
.execute();
// 3. XSS Prevention
import DOMPurify from 'dompurify';
function renderUserContent(html: string): string {
// Sanitize HTML before rendering
return DOMPurify.sanitize(html, {
ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a'],
ALLOWED_ATTR: ['href'],
});
}
// 4. CSRF Protection
import { generateToken, validateToken } from 'csrf';
const csrfToken = generateToken(req);
res.cookie('XSRF-TOKEN', csrfToken, {
httpOnly: false, // JavaScript needs to read this
secure: true,
sameSite: 'strict',
});
// Validate on state-changing requests
if (!validateToken(req.body._csrf, req.cookies['XSRF-TOKEN'])) {
throw new Error('CSRF validation failed');
}
// 5. Secure Session Management
const sessionConfig = {
secret: process.env.SESSION_SECRET!,
resave: false,
saveUninitialized: false,
cookie: {
httpOnly: true,
secure: true, // HTTPS only
sameSite: 'strict' as const,
maxAge: 3600000, // 1 hour
},
};Code Review Checklist:
- All user inputs validated
- No hardcoded secrets or credentials
- Parameterized queries used (no string concatenation)
- Output encoding applied
- Authentication and authorization implemented
- Sensitive data encrypted
- Error messages don't leak information
- Security test cases included
Reference: Secure Development Policy - Phase 2: Development
Security Testing Types:
# ✅ GOOD: CodeQL SAST configuration
name: Security Scanning - SAST
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
codeql:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: javascript, typescript
queries: security-and-quality
- name: Autobuild
uses: github/codeql-action/autobuild@v3
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3// ✅ GOOD: OWASP ZAP integration
import { ZapClient } from 'zaproxy';
async function runDAST(targetUrl: string): Promise<DastResults> {
const zap = new ZapClient({
apiKey: process.env.ZAP_API_KEY,
proxy: 'http://localhost:8080',
});
// Spider the application
await zap.spider.scan(targetUrl);
await zap.spider.waitForComplete();
// Active scan for vulnerabilities
await zap.ascan.scan(targetUrl);
await zap.ascan.waitForComplete();
// Get alerts
const alerts = await zap.core.alerts();
return {
targetUrl,
scanDate: new Date(),
alerts: alerts.filter(a => a.risk !== 'Informational'),
};
}# ✅ GOOD: Multi-tool dependency scanning
npm audit --audit-level=high
npm run snyk-test
trivy fs --scanners vuln .IAST: Use runtime security monitoring (e.g., Contrast agent) during test environments to detect vulnerabilities at execution time.
Penetration Testing Checklist:
- Pre-engagement: scope definition, rules of engagement, legal authorization
- Testing: recon, vuln scanning, exploitation, privilege escalation, lateral movement, data exfiltration
- Reporting: executive summary, CVSS-scored findings, PoC, remediation, retest
Reference: Secure Development Policy - Phase 3: Security Testing
Secure Deployment Checklist:
// ✅ GOOD: Secure deployment configuration
interface DeploymentSecurityConfig {
readonly environment: 'development' | 'staging' | 'production';
readonly securityHeaders: Record<string, string>;
readonly corsPolicy: {
readonly allowedOrigins: readonly string[];
readonly allowedMethods: readonly string[];
};
readonly rateLimiting: {
readonly enabled: boolean;
readonly maxRequests: number;
readonly windowMs: number;
};
readonly secretsManagement: {
readonly provider: 'AWS_SecretsManager' | 'Azure_KeyVault';
readonly rotationEnabled: boolean;
};
}
const PRODUCTION_CONFIG: DeploymentSecurityConfig = {
environment: 'production',
securityHeaders: {
'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',
'X-Content-Type-Options': 'nosniff',
'X-Frame-Options': 'DENY',
'Content-Security-Policy': "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline';",
'X-XSS-Protection': '1; mode=block',
},
corsPolicy: {
allowedOrigins: ['https://cia-compliance-manager.com'],
allowedMethods: ['GET', 'POST', 'PUT', 'DELETE'],
},
rateLimiting: {
enabled: true,
maxRequests: 100,
windowMs: 60000, // 1 minute
},
secretsManagement: {
provider: 'AWS_SecretsManager',
rotationEnabled: true,
},
};Deployment Security Gates:
- All security tests passed
- No critical or high vulnerabilities
- Secrets rotated and not in code
- Security headers configured
- TLS/SSL certificates valid
- Least privilege IAM roles
- Monitoring and alerting enabled
Reference: Secure Development Policy - Phase 4: Deployment
Ongoing Security Activities:
- Monitor security metrics (auth failures, rate limit exceeded, suspicious requests)
- Track patch status (pending critical/high vulnerabilities)
- Auto-response for critical threats (e.g., trigger incident response for potential DDoS)
- Regular maintenance: rotate secrets, update dependencies, review access logs, validate backups
Vulnerability Management SLA (from Vulnerability Management Policy):
- 🔴 Critical: 24 hours
- 🟠 High: 7 days
- 🟡 Medium: 30 days
- 🟢 Low: 90 days
Reference: Secure Development Policy - Phase 5: Maintenance & Operations
CRITICAL: GitHub Copilot custom agents are used extensively in Hack23's development process. These controls ensure AI-generated code maintains security standards.
RULE: AI-generated code is a proposal that MUST be reviewed by humans for security.
// ✅ GOOD: AI-generated code with human security review
/**
* 🤖 COPILOT GENERATED - CEO REVIEW REQUIRED
*
* Security Review Checklist:
* - [x] Input validation implemented
* - [x] No hardcoded secrets
* - [x] Error handling doesn't leak information
* - [x] Authentication required
* - [x] Authorization enforced
* - [x] Security tests included
*
* Reviewed by: James Pether Sörling, CEO
* Review Date: 2026-02-10
*/
async function processPayment(amount: number, userId: string): Promise<PaymentResult> {
// AI-generated implementation with security controls
// ... (code validated by human reviewer)
}MANDATORY: All AI-generated PRs require CEO approval before merge.
# ✅ GOOD: CODEOWNERS for AI agent PRs
# .github/CODEOWNERS
# AI agent branches require CEO review
copilot/** @pethers
# Security-critical paths
src/auth/** @pethers
src/services/** @pethers
.github/workflows/** @pethersContext: The agent-curator org-level agent maintains agent configurations, not application code.
Security Boundary: Agent curator changes MUST NOT bypass security reviews for application code.
Data Protection: No PII in prompts, no secrets in context, ISMS context required. Code Generation: Human review required, security tests required, CEO approval for merge. Audit Trail: GitHub logs complete, PR description required, change justification required.
Reference:
- Secure Development Policy - AI-Augmented Development Controls
- AI Governance Policy
- OWASP LLM Security Policy
MUST Requirements:
- 📊 80%+ overall test coverage
- 📊 100% coverage for security-critical paths (authentication, authorization, data handling)
- 📊 All edge cases and error scenarios tested
// ✅ GOOD: Comprehensive security test coverage
describe('UserAuthentication', () => {
describe('Security Tests', () => {
it('should reject invalid credentials', async () => {
await expect(
authenticateUser('user@example.com', 'wrong_password')
).rejects.toThrow('Invalid credentials');
});
it('should enforce rate limiting', async () => {
// Attempt 6 failed logins (limit is 5)
for (let i = 0; i < 6; i++) {
try {
await authenticateUser('user@example.com', 'wrong');
} catch (e) {
// Expected failures
}
}
// 6th attempt should be rate limited
await expect(
authenticateUser('user@example.com', 'correct_password')
).rejects.toThrow('Rate limit exceeded');
});
it('should sanitize error messages', async () => {
try {
await authenticateUser('invalid-email', 'password');
} catch (error) {
// Should NOT reveal whether user exists
expect(error.message).not.toContain('user not found');
expect(error.message).toBe('Invalid credentials');
}
});
it('should enforce session timeout', async () => {
const session = await createSession('user@example.com');
// Fast-forward time
jest.advanceTimersByTime(3600000 + 1000); // 1 hour + 1 second
await expect(
validateSession(session.token)
).rejects.toThrow('Session expired');
});
});
});Security E2E Tests:
// ✅ GOOD: E2E security testing with Cypress
describe('E2E Security Tests', () => {
it('should enforce authentication on protected routes', () => {
// Attempt to access protected route without auth
cy.visit('/dashboard', { failOnStatusCode: false });
// Should redirect to login
cy.url().should('include', '/login');
});
it('should prevent XSS attacks', () => {
const xssPayload = '<script>alert("XSS")</script>';
cy.login('test@example.com', 'password');
cy.visit('/profile');
cy.get('[data-testid="display-name-input"]').type(xssPayload);
cy.get('[data-testid="save-button"]').click();
// Verify script tag was sanitized
cy.get('[data-testid="display-name-display"]')
.should('not.contain', '<script>');
});
it('should enforce CSRF protection', () => {
cy.login('test@example.com', 'password');
// Attempt state-changing request without CSRF token
cy.request({
method: 'POST',
url: '/api/profile/update',
failOnStatusCode: false,
body: { name: 'Hacker' },
headers: {
// Missing CSRF token
},
}).then((response) => {
expect(response.status).to.eq(403);
expect(response.body.error).to.contain('CSRF');
});
});
});Reference:
SHOULD: Maintain public vulnerability disclosure process. Report to security@hack23.com (24h SLA). Rewards: Critical €500-€2K, High €200-€500, Medium €50-€200, Low: Recognition. Scope: web app, API, open source repos. Out of scope: third-party services, social engineering, physical/DoS attacks.
Reference: Vulnerability Management Policy
When logging: Never log passwords/tokens/PII. Log security events (auth failures, permission denials). Implement log retention policies.
Security is not optional. Security is not an afterthought. Security is built-in from the first line of code.
Every code change is a potential attack vector. Think like an attacker, code like a defender.
- 🛠️ Secure Development Policy - Comprehensive 95KB guide covering all SDLC phases
- 🎯 Threat Modeling Policy - STRIDE, MITRE ATT&CK, risk-based security design
- 🔍 Vulnerability Management - Security testing framework and SLA requirements
- 📊 Risk Assessment Methodology - Risk quantification and prioritization
- 🔒 Cryptography Policy - Encryption standards and key management
- 📊 Data Classification Policy - CIA Triad classification framework
- 🤖 AI Governance Policy - AI-first operations and GitHub Copilot governance
- 🛡️ OWASP LLM Security Policy - LLM Top 10 2025 security controls
- 📊 Security Metrics - KPIs for security program effectiveness
- 🎯 CLASSIFICATION Framework - Business impact analysis
- 🎯 STYLE_GUIDE - Documentation standards and emoji icons
- Threat Modeling Skill - STRIDE framework, DFD, attack surface analysis
- ISMS Compliance Skill - Framework alignment (ISO 27001, NIST CSF, CIS)
- Data Protection Skill - Privacy by Design, GDPR compliance
- Testing Excellence Skill - Comprehensive testing pyramid
- Code Quality Excellence Skill - Quality-first development
- AI Governance Skill - EU AI Act, OWASP LLM Top 10
- Compliance Frameworks Skill - Multi-framework compliance mapping
- OWASP Top 10 (2021) - Most critical web application security risks
- OWASP ASVS 4.0 - Application Security Verification Standard
- OWASP Testing Guide v4.2 - Comprehensive security testing methodology
- CWE/SANS Top 25 - Most dangerous software weaknesses
- MITRE ATT&CK Framework - Adversary tactics and techniques
- NIST Secure Software Development Framework (SSDF) - Security practices for SDLC
- ISO/IEC 27034 - Application security standard
- CERT Secure Coding Standards - Language-specific secure coding
- GitHub Security Best Practices - GitHub-native security features
- Snyk Vulnerability Database - Open source vulnerability intelligence
| Control | Description |
|---|---|
| A.5.23 | Cloud services security |
| A.8.25 | Secure development life cycle |
| A.8.26 | Security requirements & threat modeling |
| A.8.27 | Defense in depth architecture |
| A.8.28 | Secure coding (OWASP Top 10) |
| A.8.29 | Security testing (SAST/DAST/SCA/IAST/pentest) |
| A.8.30 | Third-party component risk |
| A.8.31 | Environment separation |
| A.8.32 | Security gates in deployment |
| A.8.33 | Test data protection |
GV.SC-01 (supply chain risk), ID.RA-01 (vulnerability docs), PR.DS-02 (data-in-transit/TLS), PR.DS-05 (data leak protection), PR.DS-06 (integrity/code signing), PR.IP-01 (secure defaults), PR.IP-02 (SDLC management), DE.CM-04 (malicious code detection), RS.AN-05 (vulnerability response)
Control 2 (software asset inventory), Control 3 (data protection/encryption), Control 16 (application security: 16.1-16.14 covering secure dev process, vulnerability management, root cause analysis, third-party components, hardening, env separation, developer training, secure design, code-level checks, pentesting, threat modeling), Control 18 (penetration testing)
This skill operationalizes Information Security Policy + Secure Development Policy into concrete SDLC gates:
| Phase | Gate (MUST) | Artifact |
|---|---|---|
| Plan | Threat model (STRIDE) + CIA impact + policy citation on issue | Issue body |
| Design | Data classification, trust boundaries, crypto choices reviewed | ADR + updated SECURITY_ARCHITECTURE.md |
| Build | Input validation at boundaries, no any, no secrets in source |
CI: lint, strict TS, secret scanning |
| Test | 80%+ cov (100% security-critical), negative/abuse tests, a11y | Vitest + Cypress reports |
| Review | Peer + security review, CodeQL + Dependabot green | PR approvals, scan results |
| Release | SBOM + SLSA provenance, CHANGELOG, version bump | Release artifacts |
| Operate | Vulnerability SLA tracking (24h/7d/30d/90d), incident runbook ready | Dependabot, ZAP, Incident_Response_Plan |