📦 deps(thirdparty): update snapshots
This commit is contained in:
@@ -0,0 +1,335 @@
|
||||
---
|
||||
name: security
|
||||
description: This skill should be used when auditing code for security issues, reviewing authentication/authorization, evaluating input validation, analyzing cryptographic usage, or reviewing dependency security. Provides OWASP patterns, CWE analysis, and threat modeling guidance.
|
||||
metadata:
|
||||
version: "1.0.0"
|
||||
---
|
||||
|
||||
# Security Engineering
|
||||
|
||||
Threat-aware code review. Vulnerability detection. Risk-ranked remediation.
|
||||
|
||||
<when_to_use>
|
||||
|
||||
- Security audits and code reviews
|
||||
- Authentication/authorization review
|
||||
- Input validation and sanitization checks
|
||||
- Cryptographic implementation review
|
||||
- Dependency and supply chain security
|
||||
- Threat modeling for new features
|
||||
|
||||
NOT for: performance optimization, general code review, feature implementation
|
||||
|
||||
</when_to_use>
|
||||
|
||||
<stages>
|
||||
|
||||
Load the **maintain-tasks** skill for stage tracking. Each stage feeds the next.
|
||||
|
||||
| Stage | Trigger | activeForm |
|
||||
|-------|---------|------------|
|
||||
| Threat Model | Session start | "Building threat model" |
|
||||
| Attack Surface | Model complete | "Mapping attack surface" |
|
||||
| Vulnerability Scan | Surface mapped | "Scanning for vulnerabilities" |
|
||||
| Risk Assessment | Vulns identified | "Assessing risk levels" |
|
||||
| Remediation Plan | Risks assessed | "Planning remediation" |
|
||||
|
||||
Critical findings: add urgent remediation task immediately.
|
||||
|
||||
</stages>
|
||||
|
||||
<severity_levels>
|
||||
|
||||
CVSS-aligned severity for findings:
|
||||
|
||||
| Indicator | Severity | CVSS | Examples |
|
||||
|-----------|----------|------|----------|
|
||||
| **Critical** | 9.0-10.0 | RCE, auth bypass, mass data exposure, admin privesc |
|
||||
| **High** | 7.0-8.9 | SQLi, stored XSS, auth weakness, sensitive data leak |
|
||||
| **Medium** | 4.0-6.9 | CSRF, reflected XSS, info disclosure, weak crypto |
|
||||
| **Low** | 0.1-3.9 | Misconfig, missing headers, verbose errors |
|
||||
|
||||
Format: "**Critical** RCE via unsanitized shell command"
|
||||
|
||||
</severity_levels>
|
||||
|
||||
<threat_modeling>
|
||||
|
||||
## STRIDE Framework
|
||||
|
||||
Systematic threat identification by category:
|
||||
|
||||
| Threat | Question | Check |
|
||||
|--------|----------|-------|
|
||||
| **S**poofing | Can attacker impersonate? | Auth mechanisms, tokens, sessions, API keys |
|
||||
| **T**ampering | Can attacker modify data? | Input validation, integrity checks, DB access |
|
||||
| **R**epudiation | Can actions be denied? | Audit logs, signatures, timestamps |
|
||||
| **I**nfo Disclosure | Can attacker access secrets? | Encryption, access control, logging |
|
||||
| **D**enial of Service | Can attacker disrupt? | Rate limits, timeouts, input size |
|
||||
| **E**levation | Can attacker gain access? | Authz checks, RBAC, least privilege |
|
||||
|
||||
## Attack Trees
|
||||
|
||||
Map paths from attacker goal to entry points:
|
||||
|
||||
```
|
||||
Goal: Steal credentials
|
||||
- Attack login
|
||||
- SQLi in username
|
||||
- Brute force (no rate limit)
|
||||
- Session fixation
|
||||
- Intercept traffic
|
||||
- HTTPS downgrade
|
||||
- MITM
|
||||
- Exploit reset
|
||||
- Predictable token
|
||||
- No expiry
|
||||
```
|
||||
|
||||
For each branch assess: feasibility, impact, detection, current defenses.
|
||||
|
||||
## Trust Boundaries
|
||||
|
||||
Identify where data crosses trust levels:
|
||||
- Browser to server
|
||||
- Server to database
|
||||
- Service to third-party API
|
||||
- Internal service to service
|
||||
|
||||
Every boundary needs validation.
|
||||
|
||||
</threat_modeling>
|
||||
|
||||
<attack_surface>
|
||||
|
||||
## Entry Points
|
||||
|
||||
**External**:
|
||||
- HTTP/API endpoints (REST, GraphQL, gRPC)
|
||||
- WebSocket connections
|
||||
- File uploads
|
||||
- OAuth/SAML flows
|
||||
- Webhooks
|
||||
|
||||
**Data Inputs**:
|
||||
- User data (forms, query params, headers)
|
||||
- File content (type, size, payload)
|
||||
- API payloads (JSON, XML)
|
||||
- Database queries
|
||||
|
||||
**Auth Boundaries**:
|
||||
- Public (no auth)
|
||||
- Authenticated
|
||||
- Admin/privileged
|
||||
- Service-to-service
|
||||
|
||||
## Prioritize Review
|
||||
|
||||
1. Unauthenticated external inputs
|
||||
2. Privileged operations
|
||||
3. Data persistence layers
|
||||
4. Third-party integrations
|
||||
|
||||
For each entry point document:
|
||||
- Auth required? (none/user/admin)
|
||||
- Input validated? (none/basic/strict)
|
||||
- Rate limited?
|
||||
- Logged?
|
||||
- Encrypted?
|
||||
|
||||
</attack_surface>
|
||||
|
||||
<vulnerability_patterns>
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Vulnerability | Vulnerable | Secure |
|
||||
|--------------|------------|--------|
|
||||
| SQL Injection | String concat in query | Parameterized queries |
|
||||
| XSS | innerHTML with user data | textContent or DOMPurify |
|
||||
| Command Injection | exec() with user input | execFile() with array |
|
||||
| Path Traversal | Direct path concat | basename + prefix check |
|
||||
| Weak Password | MD5/SHA1/plain | bcrypt (12+) or argon2 |
|
||||
| Predictable Token | Math.random/Date.now | crypto.randomBytes(32) |
|
||||
| Broken Auth | Client-side role check | Server-side every request |
|
||||
| IDOR | No ownership check | Verify user owns resource |
|
||||
| Hardcoded Secret | API key in code | Environment variable |
|
||||
| Info Leak | Stack trace to user | Generic error, log detail |
|
||||
|
||||
## Critical Checks
|
||||
|
||||
**Authentication**:
|
||||
- Passwords: bcrypt/argon2, cost 12+
|
||||
- Sessions: crypto.randomBytes(32), httpOnly, secure, sameSite
|
||||
- JWT: verify signature, specify algorithm, short expiry
|
||||
- Reset: random token, 1hr expiry, hash stored token
|
||||
|
||||
**Authorization**:
|
||||
- Server-side on every request
|
||||
- Verify ownership before resource access
|
||||
- Explicit allowlist for mass assignment
|
||||
- No role elevation from client input
|
||||
|
||||
**Input Validation**:
|
||||
- Type, length, format on all inputs
|
||||
- Parameterized queries (never concat)
|
||||
- Escape/sanitize HTML output
|
||||
- Validate file uploads (type, size, content)
|
||||
|
||||
**Cryptography**:
|
||||
- AES-256-GCM, SHA-256+
|
||||
- Never MD5, SHA1, DES, ECB
|
||||
- Secrets from env, never hardcoded
|
||||
- crypto.randomBytes for all tokens
|
||||
|
||||
See [vulnerability-patterns.md](references/vulnerability-patterns.md) for code examples.
|
||||
|
||||
</vulnerability_patterns>
|
||||
|
||||
<owasp_top_10>
|
||||
|
||||
2021 OWASP Top 10 categories. Check each during vulnerability scan.
|
||||
|
||||
| # | Category | Key CWEs | Top Mitigations |
|
||||
|---|----------|----------|-----------------|
|
||||
| A01 | Broken Access Control | 200, 352, 639 | Server-side checks, ownership validation |
|
||||
| A02 | Cryptographic Failures | 259, 327, 331 | TLS, bcrypt, no hardcoded secrets |
|
||||
| A03 | Injection | 20, 79, 89 | Parameterized queries, input validation |
|
||||
| A04 | Insecure Design | 209, 256, 434 | Threat modeling, rate limiting |
|
||||
| A05 | Security Misconfiguration | 16, 611, 614 | Security headers, disable debug |
|
||||
| A06 | Vulnerable Components | 1035, 1104 | npm audit, Dependabot |
|
||||
| A07 | Auth Failures | 287, 307, 521 | Strong passwords, MFA, rate limiting |
|
||||
| A08 | Integrity Failures | 502, 494 | Verify signatures, schema validation |
|
||||
| A09 | Logging Failures | 117, 532, 778 | Audit logs, redact sensitive data |
|
||||
| A10 | SSRF | 918 | URL allowlist, block private IPs |
|
||||
|
||||
See [owasp-top-10.md](references/owasp-top-10.md) for detailed breakdowns with code examples.
|
||||
|
||||
</owasp_top_10>
|
||||
|
||||
<workflow>
|
||||
|
||||
**Loop**: Model Threats -> Map Surface -> Scan Vulnerabilities -> Assess Risk -> Plan Remediation
|
||||
|
||||
1. **Threat Model**
|
||||
- STRIDE analysis for component
|
||||
- Attack trees for critical paths
|
||||
- Identify trust boundaries
|
||||
- Document threat actors
|
||||
|
||||
2. **Attack Surface**
|
||||
- Inventory all inputs
|
||||
- Classify by auth level
|
||||
- Map data flows across boundaries
|
||||
- Prioritize high-risk entry points
|
||||
|
||||
3. **Vulnerability Scan**
|
||||
- Check each entry against OWASP Top 10
|
||||
- Review auth/authz
|
||||
- Validate input handling
|
||||
- Check crypto usage
|
||||
- Scan deps: `npm audit`, `cargo audit`
|
||||
|
||||
4. **Risk Assessment**
|
||||
- Rate severity (Critical/High/Medium/Low)
|
||||
- Consider exploitability
|
||||
- Assess impact (CIA triad)
|
||||
- Calculate risk score
|
||||
|
||||
5. **Remediation Plan**
|
||||
- **Critical**: immediate action
|
||||
- **High**: fix before release
|
||||
- **Medium**: schedule in sprint
|
||||
- **Low**: backlog or accept
|
||||
|
||||
Update todos as you progress. Use [review-checklist.md](references/review-checklist.md) for verification.
|
||||
|
||||
</workflow>
|
||||
|
||||
<reporting>
|
||||
|
||||
## Finding Format
|
||||
|
||||
```markdown
|
||||
## {SEVERITY} {VULN_NAME}
|
||||
|
||||
**Category**: {OWASP} | **CWE**: {ID} | **File**: {PATH}:{LINES}
|
||||
|
||||
### Issue
|
||||
{CLEAR_EXPLANATION}
|
||||
|
||||
### Impact
|
||||
{WHAT_ATTACKER_COULD_DO}
|
||||
|
||||
### Fix
|
||||
{SPECIFIC_REMEDIATION_WITH_CODE}
|
||||
```
|
||||
|
||||
## Summary Format
|
||||
|
||||
```markdown
|
||||
# Security Audit: {SCOPE}
|
||||
|
||||
| Severity | Count |
|
||||
|----------|-------|
|
||||
| Critical | N |
|
||||
| High | N |
|
||||
| Medium | N |
|
||||
| Low | N |
|
||||
|
||||
## Key Findings
|
||||
1. {TOP_CRITICAL}
|
||||
2. {SECOND}
|
||||
3. {THIRD}
|
||||
|
||||
## Recommendations
|
||||
- Immediate: {CRITICAL_FIXES}
|
||||
- Short-term: {HIGH_MEDIUM}
|
||||
- Long-term: {HARDENING}
|
||||
```
|
||||
|
||||
See [report-templates.md](references/report-templates.md) for full templates.
|
||||
|
||||
</reporting>
|
||||
|
||||
<rules>
|
||||
|
||||
ALWAYS:
|
||||
- Start with threat modeling before code review
|
||||
- Map complete attack surface
|
||||
- Check against all OWASP Top 10 categories
|
||||
- Use severity indicators consistently
|
||||
- Provide specific remediation with code
|
||||
- Verify fixes don't introduce new vulnerabilities
|
||||
- Document security assumptions
|
||||
- Update todos when transitioning stages
|
||||
|
||||
NEVER:
|
||||
- Skip threat modeling for "simple" features
|
||||
- Assume input is trustworthy
|
||||
- Rely on client-side security
|
||||
- Use deprecated crypto (MD5, SHA1, DES)
|
||||
- Log sensitive data
|
||||
- Disable security checks "temporarily"
|
||||
- Mark complete without remediation plan
|
||||
|
||||
</rules>
|
||||
|
||||
<references>
|
||||
|
||||
**Deep dives**:
|
||||
- [vulnerability-patterns.md](references/vulnerability-patterns.md) - secure vs vulnerable code examples
|
||||
- [owasp-top-10.md](references/owasp-top-10.md) - detailed OWASP categories with CWE mappings
|
||||
- [review-checklist.md](references/review-checklist.md) - complete security review checklist
|
||||
- [report-templates.md](references/report-templates.md) - finding and audit report templates
|
||||
|
||||
**Related skills**:
|
||||
- codebase-recon - evidence-based investigation foundation
|
||||
- debugging - when security issues manifest as bugs
|
||||
|
||||
**External**:
|
||||
- [OWASP Top 10](https://owasp.org/Top10/)
|
||||
- [CWE Database](https://cwe.mitre.org/)
|
||||
- [OWASP Cheat Sheets](https://cheatsheetseries.owasp.org/)
|
||||
|
||||
</references>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,167 @@
|
||||
# Security Report Templates
|
||||
|
||||
Templates for documenting security findings and audit reports.
|
||||
|
||||
---
|
||||
|
||||
## Individual Finding Template
|
||||
|
||||
```markdown
|
||||
## {SEVERITY} {VULNERABILITY_NAME}
|
||||
|
||||
**Category**: {OWASP_CATEGORY}
|
||||
**CWE**: {CWE_IDS}
|
||||
**Severity**: Critical/High/Medium/Low
|
||||
|
||||
### Location
|
||||
- File: {FILE_PATH}
|
||||
- Lines: {LINE_RANGE}
|
||||
- Function: {FUNCTION_NAME}
|
||||
|
||||
### Description
|
||||
{CLEAR_EXPLANATION}
|
||||
|
||||
### Impact
|
||||
{WHAT_ATTACKER_COULD_DO}
|
||||
|
||||
### Proof of Concept
|
||||
{CODE_OR_STEPS_TO_EXPLOIT}
|
||||
|
||||
### Remediation
|
||||
{SPECIFIC_FIX_WITH_CODE}
|
||||
|
||||
### References
|
||||
- OWASP: {URL}
|
||||
- CWE: {URL}
|
||||
```
|
||||
|
||||
### Severity Indicators
|
||||
|
||||
Use these indicators in finding titles:
|
||||
|
||||
- **Critical**: Remote code execution, auth bypass, mass data exposure, admin privilege escalation
|
||||
- **High**: SQL injection, stored XSS, auth weaknesses, sensitive data leaks
|
||||
- **Medium**: CSRF, reflected XSS, information disclosure, weak crypto
|
||||
- **Low**: Misconfigurations, missing headers, verbose errors, minor info leaks
|
||||
|
||||
---
|
||||
|
||||
## Audit Report Template
|
||||
|
||||
```markdown
|
||||
# Security Audit Report
|
||||
|
||||
**Date**: {DATE}
|
||||
**Scope**: {COMPONENTS_REVIEWED}
|
||||
**Reviewer**: {NAME}
|
||||
**Version**: {APP_VERSION}
|
||||
|
||||
## Executive Summary
|
||||
|
||||
{1-2 PARAGRAPH HIGH-LEVEL OVERVIEW}
|
||||
|
||||
Overall security posture: {STRONG/ADEQUATE/NEEDS_IMPROVEMENT/CRITICAL}
|
||||
|
||||
## Risk Summary
|
||||
|
||||
| Severity | Count |
|
||||
|----------|-------|
|
||||
| Critical | {N} |
|
||||
| High | {N} |
|
||||
| Medium | {N} |
|
||||
| Low | {N} |
|
||||
|
||||
## Key Findings
|
||||
|
||||
### 1. {MOST_CRITICAL_FINDING}
|
||||
Brief description and impact.
|
||||
|
||||
### 2. {SECOND_FINDING}
|
||||
Brief description and impact.
|
||||
|
||||
### 3. {THIRD_FINDING}
|
||||
Brief description and impact.
|
||||
|
||||
## Detailed Findings
|
||||
|
||||
{FULL_LIST_USING_INDIVIDUAL_FINDING_TEMPLATE}
|
||||
|
||||
## Recommendations
|
||||
|
||||
### Immediate (Critical/High)
|
||||
1. {ACTION_ITEM}
|
||||
2. {ACTION_ITEM}
|
||||
|
||||
### Short-term (Medium)
|
||||
1. {ACTION_ITEM}
|
||||
|
||||
### Long-term (Low / Hardening)
|
||||
1. {ACTION_ITEM}
|
||||
|
||||
## Scope & Methodology
|
||||
|
||||
### In Scope
|
||||
- {COMPONENT_1}
|
||||
- {COMPONENT_2}
|
||||
|
||||
### Out of Scope
|
||||
- {EXCLUDED_ITEM}
|
||||
|
||||
### Methodology
|
||||
- Threat modeling (STRIDE)
|
||||
- Code review
|
||||
- Dependency scanning
|
||||
- {OTHER_METHODS}
|
||||
|
||||
## Conclusion
|
||||
|
||||
{OVERALL_ASSESSMENT_AND_NEXT_STEPS}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Quick Finding Format
|
||||
|
||||
For inline documentation or PR comments:
|
||||
|
||||
```
|
||||
[SEVERITY] VULN_TYPE in FILE:LINE
|
||||
- Issue: {brief description}
|
||||
- Impact: {what attacker could do}
|
||||
- Fix: {one-line remediation}
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
[HIGH] SQL Injection in src/api/users.ts:45
|
||||
- Issue: User email concatenated into query string
|
||||
- Impact: Attacker can extract/modify database
|
||||
- Fix: Use parameterized query with db.execute(sql, [email])
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Risk Matrix
|
||||
|
||||
Use for prioritization:
|
||||
|
||||
```
|
||||
IMPACT
|
||||
Low Med High
|
||||
Low Low Low Med
|
||||
LIKELIHOOD Med Low Med High
|
||||
High Med High Crit
|
||||
```
|
||||
|
||||
Factors affecting likelihood:
|
||||
- Skill required to exploit
|
||||
- Access required (unauth vs auth vs admin)
|
||||
- Attack complexity
|
||||
- User interaction needed
|
||||
|
||||
Factors affecting impact:
|
||||
- Confidentiality (data exposure)
|
||||
- Integrity (data modification)
|
||||
- Availability (service disruption)
|
||||
- Scope (single user vs all users vs system)
|
||||
@@ -0,0 +1,124 @@
|
||||
# Security Review Checklist
|
||||
|
||||
Complete checklist for security code review. Check each item before marking review complete.
|
||||
|
||||
---
|
||||
|
||||
## Authentication
|
||||
|
||||
- [ ] Passwords hashed with bcrypt/argon2 (cost >= 12)
|
||||
- [ ] Session tokens cryptographically random (32+ bytes)
|
||||
- [ ] Session cookies: httpOnly, secure, sameSite=strict
|
||||
- [ ] Password reset tokens random + expiring (1 hour max)
|
||||
- [ ] Rate limiting on login (5 attempts / 15 min)
|
||||
- [ ] Account lockout after repeated failures
|
||||
- [ ] MFA available for sensitive accounts
|
||||
- [ ] JWT: signature verified, algorithm specified
|
||||
- [ ] JWT: short expiry, refresh token rotation
|
||||
- [ ] No credentials in URLs or logs
|
||||
|
||||
## Authorization
|
||||
|
||||
- [ ] All endpoints verify authentication server-side
|
||||
- [ ] Resource ownership verified before access (no IDOR)
|
||||
- [ ] Role checks on server, never client-only
|
||||
- [ ] Principle of least privilege applied
|
||||
- [ ] Admin functions require admin role server-side
|
||||
- [ ] API endpoints return 403 for unauthorized, not 404
|
||||
- [ ] Mass assignment prevented (explicit allowlists)
|
||||
- [ ] CORS configured with explicit origins (no wildcards with credentials)
|
||||
|
||||
## Input Validation
|
||||
|
||||
- [ ] All inputs validated (type, length, format)
|
||||
- [ ] SQL queries use parameterized statements
|
||||
- [ ] HTML output escaped or sanitized (no raw innerHTML)
|
||||
- [ ] File uploads validated (type, size, content)
|
||||
- [ ] File names sanitized (path.basename)
|
||||
- [ ] Path traversal prevented (prefix check after join)
|
||||
- [ ] Command injection prevented (execFile, no shell)
|
||||
- [ ] XML parsing disables external entities
|
||||
- [ ] JSON schema validation on API inputs
|
||||
|
||||
## Cryptography
|
||||
|
||||
- [ ] No hardcoded secrets in code
|
||||
- [ ] Secrets from environment variables
|
||||
- [ ] Strong algorithms only (AES-256-GCM, SHA-256+)
|
||||
- [ ] No MD5, SHA1, DES, ECB mode
|
||||
- [ ] crypto.randomBytes for all tokens
|
||||
- [ ] No Math.random for security purposes
|
||||
- [ ] HTTPS enforced (no HTTP endpoints)
|
||||
- [ ] TLS 1.2+ required
|
||||
- [ ] Certificate validation not disabled
|
||||
- [ ] Keys rotated periodically
|
||||
|
||||
## Data Protection
|
||||
|
||||
- [ ] Sensitive data encrypted at rest
|
||||
- [ ] TLS 1.2+ for data in transit
|
||||
- [ ] Sensitive data not logged (passwords, tokens, PII)
|
||||
- [ ] Error messages generic to users, detailed in logs
|
||||
- [ ] PII handling complies with regulations (GDPR, CCPA)
|
||||
- [ ] Database credentials not in code
|
||||
- [ ] Backups encrypted
|
||||
- [ ] Data retention policies implemented
|
||||
|
||||
## Dependencies
|
||||
|
||||
- [ ] All dependencies up to date
|
||||
- [ ] npm audit / cargo audit clean
|
||||
- [ ] No known CVEs in dependencies
|
||||
- [ ] Dependency scanning in CI/CD
|
||||
- [ ] Package lock files committed
|
||||
- [ ] Minimal dependency footprint
|
||||
- [ ] Source verification for dependencies
|
||||
- [ ] No unused dependencies
|
||||
|
||||
## Logging & Monitoring
|
||||
|
||||
- [ ] Authentication events logged (success + failure)
|
||||
- [ ] Authorization failures logged
|
||||
- [ ] Sensitive operations audited (admin actions, data access)
|
||||
- [ ] Log entries include timestamp, user ID, IP, action
|
||||
- [ ] Logs protected from tampering
|
||||
- [ ] No sensitive data in logs
|
||||
- [ ] Log injection prevented (sanitize user input in logs)
|
||||
- [ ] Security events trigger alerts
|
||||
- [ ] Incident response plan documented
|
||||
|
||||
## Infrastructure
|
||||
|
||||
- [ ] Security headers configured (helmet or equivalent)
|
||||
- [ ] Content-Security-Policy
|
||||
- [ ] X-Content-Type-Options: nosniff
|
||||
- [ ] X-Frame-Options: DENY
|
||||
- [ ] Strict-Transport-Security
|
||||
- [ ] Referrer-Policy
|
||||
- [ ] Debug mode disabled in production
|
||||
- [ ] Default accounts/passwords changed
|
||||
- [ ] Unnecessary features/endpoints disabled
|
||||
- [ ] Error pages don't reveal stack traces
|
||||
- [ ] Rate limiting on all public endpoints
|
||||
|
||||
## SSRF Prevention
|
||||
|
||||
- [ ] URL inputs validated against allowlist
|
||||
- [ ] Private IPs blocked (10.x, 172.16-31.x, 192.168.x, 127.x, 169.254.x)
|
||||
- [ ] Cloud metadata endpoints blocked (169.254.169.254)
|
||||
- [ ] Redirect following disabled or validated
|
||||
- [ ] DNS rebinding prevented
|
||||
|
||||
---
|
||||
|
||||
## Quick Pre-Commit Checklist
|
||||
|
||||
Minimum checks before any commit touching security-sensitive code:
|
||||
|
||||
1. [ ] No hardcoded secrets
|
||||
2. [ ] Inputs validated
|
||||
3. [ ] SQL parameterized
|
||||
4. [ ] Auth checked server-side
|
||||
5. [ ] Ownership verified for resources
|
||||
6. [ ] Sensitive data not logged
|
||||
7. [ ] npm audit clean
|
||||
+298
@@ -0,0 +1,298 @@
|
||||
# Vulnerability Patterns Reference
|
||||
|
||||
Secure vs vulnerable code patterns organized by category. Each pattern shows the vulnerability and its remediation.
|
||||
|
||||
---
|
||||
|
||||
## Input Validation
|
||||
|
||||
### SQL Injection
|
||||
|
||||
```typescript
|
||||
// VULNERABLE
|
||||
const query = `SELECT * FROM users WHERE email = '${userEmail}'`;
|
||||
|
||||
// SECURE - parameterized queries
|
||||
const query = 'SELECT * FROM users WHERE email = ?';
|
||||
db.execute(query, [userEmail]);
|
||||
```
|
||||
|
||||
### XSS (Cross-Site Scripting)
|
||||
|
||||
```typescript
|
||||
// VULNERABLE - direct HTML insertion
|
||||
element.innerHTML = userInput;
|
||||
|
||||
// SECURE - use textContent or sanitize
|
||||
element.textContent = userInput;
|
||||
// OR for rich content
|
||||
element.innerHTML = DOMPurify.sanitize(userInput);
|
||||
```
|
||||
|
||||
### Command Injection
|
||||
|
||||
```typescript
|
||||
// VULNERABLE
|
||||
exec(`convert ${userFilename} output.png`);
|
||||
|
||||
// SECURE - parameterized or allowlist
|
||||
execFile('convert', [userFilename, 'output.png']);
|
||||
```
|
||||
|
||||
### Path Traversal
|
||||
|
||||
```typescript
|
||||
// VULNERABLE
|
||||
const filePath = `/uploads/${userFileName}`;
|
||||
|
||||
// SECURE - validate and normalize
|
||||
const safeName = path.basename(userFileName);
|
||||
const filePath = path.join('/uploads', safeName);
|
||||
if (!filePath.startsWith('/uploads/')) {
|
||||
throw new Error('Invalid path');
|
||||
}
|
||||
```
|
||||
|
||||
### XXE (XML External Entity)
|
||||
|
||||
```typescript
|
||||
// VULNERABLE
|
||||
const parser = new DOMParser();
|
||||
const doc = parser.parseFromString(xmlInput, 'text/xml');
|
||||
|
||||
// SECURE - disable external entities
|
||||
const parser = new DOMParser({
|
||||
locator: {},
|
||||
errorHandler: {},
|
||||
entityResolver: () => null, // Disable DTD processing
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Authentication & Sessions
|
||||
|
||||
### Password Storage
|
||||
|
||||
```typescript
|
||||
// VULNERABLE - plain text or weak hash
|
||||
const hash = md5(password);
|
||||
|
||||
// SECURE - bcrypt/argon2 with salt
|
||||
const hash = await bcrypt.hash(password, 12);
|
||||
```
|
||||
|
||||
### Session Management
|
||||
|
||||
```typescript
|
||||
// VULNERABLE - predictable session IDs
|
||||
const sessionId = userId + Date.now();
|
||||
|
||||
// SECURE - cryptographically random
|
||||
const sessionId = crypto.randomBytes(32).toString('hex');
|
||||
|
||||
// Security attributes
|
||||
res.cookie('session', sessionId, {
|
||||
httpOnly: true,
|
||||
secure: true, // HTTPS only
|
||||
sameSite: 'strict',
|
||||
maxAge: 3600000, // 1 hour
|
||||
});
|
||||
```
|
||||
|
||||
### JWT Handling
|
||||
|
||||
```typescript
|
||||
// VULNERABLE - no signature verification
|
||||
const payload = JSON.parse(atob(token.split('.')[1]));
|
||||
|
||||
// SECURE - verify signature
|
||||
const payload = jwt.verify(token, SECRET_KEY, {
|
||||
algorithms: ['HS256'], // Specify allowed algorithms
|
||||
issuer: 'your-app',
|
||||
audience: 'your-api',
|
||||
});
|
||||
```
|
||||
|
||||
### Password Reset
|
||||
|
||||
```typescript
|
||||
// VULNERABLE - predictable tokens
|
||||
const resetToken = userId + '-' + Date.now();
|
||||
|
||||
// SECURE - cryptographically random with expiry
|
||||
const resetToken = crypto.randomBytes(32).toString('hex');
|
||||
await db.execute(
|
||||
'INSERT INTO reset_tokens (user_id, token, expires_at) VALUES (?, ?, ?)',
|
||||
[userId, await bcrypt.hash(resetToken, 10), Date.now() + 3600000]
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Authorization
|
||||
|
||||
### Broken Access Control
|
||||
|
||||
```typescript
|
||||
// VULNERABLE - client-side only check
|
||||
if (user.isAdmin) {
|
||||
// show admin panel
|
||||
}
|
||||
|
||||
// SECURE - server-side enforcement
|
||||
app.get('/admin/users', requireAdmin, (req, res) => {
|
||||
if (!req.user?.isAdmin) {
|
||||
return res.status(403).json({ error: 'Forbidden' });
|
||||
}
|
||||
// Admin operation
|
||||
});
|
||||
```
|
||||
|
||||
### IDOR (Insecure Direct Object Reference)
|
||||
|
||||
```typescript
|
||||
// VULNERABLE - no ownership check
|
||||
app.get('/api/documents/:id', async (req, res) => {
|
||||
const doc = await db.getDocument(req.params.id);
|
||||
res.json(doc);
|
||||
});
|
||||
|
||||
// SECURE - verify ownership
|
||||
app.get('/api/documents/:id', async (req, res) => {
|
||||
const doc = await db.getDocument(req.params.id);
|
||||
if (doc.userId !== req.user.id && !req.user.isAdmin) {
|
||||
return res.status(403).json({ error: 'Forbidden' });
|
||||
}
|
||||
res.json(doc);
|
||||
});
|
||||
```
|
||||
|
||||
### Privilege Escalation
|
||||
|
||||
```typescript
|
||||
// VULNERABLE - role from client input
|
||||
app.post('/api/users', async (req, res) => {
|
||||
const user = await createUser({
|
||||
...req.body, // Includes role: 'admin' from malicious client
|
||||
});
|
||||
});
|
||||
|
||||
// SECURE - explicit allowlist
|
||||
app.post('/api/users', async (req, res) => {
|
||||
const allowedFields = ['name', 'email', 'password'];
|
||||
const userData = pick(req.body, allowedFields);
|
||||
const user = await createUser({
|
||||
...userData,
|
||||
role: 'user', // Server controls role
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Cryptography
|
||||
|
||||
### Weak Algorithms
|
||||
|
||||
```typescript
|
||||
// VULNERABLE - deprecated algorithms
|
||||
const hash = crypto.createHash('md5').update(data).digest('hex');
|
||||
const cipher = crypto.createCipher('des', key);
|
||||
|
||||
// SECURE - modern algorithms
|
||||
const hash = crypto.createHash('sha256').update(data).digest('hex');
|
||||
const cipher = crypto.createCipheriv('aes-256-gcm', key, iv);
|
||||
```
|
||||
|
||||
### Hardcoded Secrets
|
||||
|
||||
```typescript
|
||||
// VULNERABLE
|
||||
const API_KEY = 'sk-1234567890abcdef';
|
||||
const DB_PASSWORD = 'admin123';
|
||||
|
||||
// SECURE - environment variables
|
||||
const API_KEY = process.env.API_KEY;
|
||||
const DB_PASSWORD = process.env.DB_PASSWORD;
|
||||
|
||||
if (!API_KEY || !DB_PASSWORD) {
|
||||
throw new Error('Missing required environment variables');
|
||||
}
|
||||
```
|
||||
|
||||
### Insufficient Randomness
|
||||
|
||||
```typescript
|
||||
// VULNERABLE - predictable
|
||||
const token = Math.random().toString(36);
|
||||
|
||||
// SECURE - cryptographically secure
|
||||
const token = crypto.randomBytes(32).toString('hex');
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Data Exposure
|
||||
|
||||
### Sensitive Data in Logs
|
||||
|
||||
```typescript
|
||||
// VULNERABLE
|
||||
logger.info('User login', { email, password, ssn });
|
||||
|
||||
// SECURE - redact sensitive fields
|
||||
logger.info('User login', {
|
||||
email,
|
||||
password: '[REDACTED]',
|
||||
ssn: '[REDACTED]',
|
||||
});
|
||||
```
|
||||
|
||||
### Error Message Disclosure
|
||||
|
||||
```typescript
|
||||
// VULNERABLE - exposes internals
|
||||
catch (err) {
|
||||
res.status(500).json({ error: err.stack });
|
||||
}
|
||||
|
||||
// SECURE - generic message
|
||||
catch (err) {
|
||||
logger.error('Internal error', err);
|
||||
res.status(500).json({ error: 'Internal server error' });
|
||||
}
|
||||
```
|
||||
|
||||
### Timing Attacks
|
||||
|
||||
```typescript
|
||||
// VULNERABLE - early exit leaks info
|
||||
if (user.password !== inputPassword) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// SECURE - constant-time comparison
|
||||
return crypto.timingSafeEqual(
|
||||
Buffer.from(user.password),
|
||||
Buffer.from(inputPassword)
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Category | Vulnerable Pattern | Secure Pattern |
|
||||
|----------|-------------------|----------------|
|
||||
| SQL Injection | String concatenation | Parameterized queries |
|
||||
| XSS | innerHTML with user input | textContent or DOMPurify |
|
||||
| Command Injection | exec() with user input | execFile() with array args |
|
||||
| Path Traversal | Direct path concat | path.basename + prefix check |
|
||||
| Password Storage | MD5/SHA1/plain | bcrypt (cost 12+) or argon2 |
|
||||
| Session IDs | Predictable (Date.now) | crypto.randomBytes(32) |
|
||||
| JWT | Skip verification | jwt.verify() with algorithm |
|
||||
| Access Control | Client-side only | Server-side on every request |
|
||||
| IDOR | No ownership check | Verify user owns resource |
|
||||
| Secrets | Hardcoded in code | Environment variables |
|
||||
| Error Messages | Stack traces to users | Generic error + log details |
|
||||
Reference in New Issue
Block a user