# Security Review

> Use when writing code that handles user input, authentication, authorization, data storage, external APIs, file operations, or any security-sensitive functionality. Also use proactively before commits and during code review.

- Skill: `tomevault-io/security-review-24` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add tomevault-io/security-review-24`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tomevault-io/security-review-24/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: tomevault-io (https://skillmd.com/u/tomevault-io)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/tomevault-io/security-review-24

---


# Security Review

## Overview

Security vulnerabilities are not bugs to fix later - they are design failures to prevent now. Every line of code that touches untrusted data is a potential attack vector.

**Core principle:** ASSUME ALL INPUT IS HOSTILE. Validate, sanitize, and escape at every boundary.

**The cost equation:** 1 hour of security review saves 100 hours of incident response.

## When to Use

**ALWAYS use this skill when:**
- Handling ANY user input (forms, URLs, headers, files)
- Implementing authentication or authorization
- Working with databases or data storage
- Making external API calls
- Processing files or file paths
- Handling secrets, tokens, or credentials
- Implementing cryptographic operations
- Working with session management
- Before committing security-sensitive code
- During code review

**Use ESPECIALLY when:**
- Building public-facing features
- Handling payment or financial data
- Processing personal/sensitive information
- Implementing admin functionality
- Creating APIs consumed by others
- Working in unfamiliar security domains

## The Security Mindset

```
NEVER TRUST:
├── User input (forms, URLs, headers, cookies)
├── Data from external APIs
├── File contents or filenames
├── Database values (could be previously injected)
├── Environment variables (in shared environments)
├── URL parameters and fragments
└── Anything not generated by YOUR code in THIS request
```

Think like an attacker:
- "What if I send 10MB of data here?"
- "What if this string contains SQL/HTML/shell commands?"
- "What if I access this without authentication?"
- "What if I tamper with this client-side value?"
- "What if I call this API endpoint directly?"

## The Three Phases

### Phase 1: Threat Assessment

**Before writing code, identify threats:**

1. **Data Flow Analysis**
   ```
   For each feature, map:
   ├── INPUT: Where does data enter?
   │   └── User form? API? File upload? URL?
   ├── PROCESS: What operations occur?
   │   └── Database query? File operation? Shell command?
   ├── OUTPUT: Where does data go?
   │   └── HTML page? API response? Log file?
   └── STORAGE: What persists?
       └── Database? Session? Cookie? File?
   ```

2. **Attack Surface Identification**
   ```
   List every:
   ├── Public endpoint
   ├── Input field
   ├── File upload
   ├── API parameter
   ├── Authentication point
   └── Authorization check
   ```

3. **STRIDE Threat Modeling**

   | Threat | Question | Example |
   |--------|----------|---------|
   | **S**poofing | Can attacker pretend to be someone else? | Session hijacking |
   | **T**ampering | Can attacker modify data? | Parameter manipulation |
   | **R**epudiation | Can attacker deny actions? | Missing audit logs |
   | **I**nformation Disclosure | Can attacker access secrets? | Error message leaks |
   | **D**enial of Service | Can attacker crash/slow system? | Resource exhaustion |
   | **E**levation of Privilege | Can attacker gain higher access? | Broken access control |

See: [references/threat-modeling.md](references/threat-modeling.md)

### Phase 2: Secure Implementation

**Apply defense-in-depth at every layer:**

#### Input Validation (First Line of Defense)

```
VALIDATE EARLY, VALIDATE STRICTLY:

1. Type checking     - Is it the expected type?
2. Length limits     - Is it within acceptable bounds?
3. Format validation - Does it match expected pattern?
4. Range checking    - Is numeric value in valid range?
5. Allowlist         - Is it in the set of allowed values?
```

**Validation patterns:**

```typescript
// GOOD: Strict validation with allowlist
const ALLOWED_ROLES = ['user', 'editor', 'admin'] as const;
type Role = typeof ALLOWED_ROLES[number];

function setUserRole(role: string): Role {
  if (!ALLOWED_ROLES.includes(role as Role)) {
    throw new ValidationError('Invalid role');
  }
  return role as Role;
}
```

#### Output Encoding (Prevent Injection)

```
ENCODE FOR CONTEXT:

HTML body    → HTML entity encoding (&lt; &gt; &amp;)
HTML attr    → Attribute encoding (additional chars)
JavaScript   → JavaScript encoding (\xNN)
URL          → URL encoding (%XX)
CSS          → CSS encoding
SQL          → Parameterized queries (NEVER string concat)
Shell        → Avoid entirely, or use execFile with args array
```

**Context-aware encoding:**

```typescript
// HTML context - use textContent or sanitize with DOMPurify
const safeText = document.createTextNode(userInput);
element.appendChild(safeText);

// URL context - encode for URL
const userUrl = encodeURIComponent(userInput);
const url = `/search?q=${userUrl}`;

// SQL context - ALWAYS parameterize
const result = await db.query(
  'SELECT * FROM users WHERE id = $1',
  [userId]  // Parameterized, never concatenated
);
```

#### Authentication Security

```
AUTHENTICATION CHECKLIST:

□ Passwords hashed with bcrypt/argon2 (cost factor >= 10)
□ No password in logs, errors, or responses
□ Rate limiting on login attempts
□ Account lockout after N failures
□ Secure session generation (crypto random)
□ Session invalidation on logout
□ Session timeout (idle and absolute)
□ HTTPS only for credentials
□ No credentials in URL parameters
□ Multi-factor where possible
```

#### Authorization Security

```
AUTHORIZATION CHECKLIST:

□ Check permissions on EVERY request
□ Deny by default, explicitly allow
□ Verify ownership for resource access
□ Re-validate on sensitive operations
□ No client-side only authorization
□ Audit log authorization failures
□ Principle of least privilege
□ Time-limited access tokens
```

**Authorization patterns:**

```typescript
// GOOD: Explicit ownership check
async function getDocument(userId: string, docId: string) {
  const doc = await db.documents.findById(docId);

  if (!doc) throw new NotFoundError();
  if (doc.ownerId !== userId && !doc.sharedWith.includes(userId)) {
    throw new ForbiddenError(); // Don't reveal existence
  }

  return doc;
}
```

See: [references/secure-coding-patterns.md](references/secure-coding-patterns.md)

### Phase 3: Verification

**Verify security controls are effective:**

1. **Manual Testing**
   ```
   For each input:
   □ Test with malicious payloads (XSS, SQLi, etc.)
   □ Test boundary conditions (empty, max length, overflow)
   □ Test type confusion (array vs string, int vs float)
   □ Test encoding bypass attempts
   ```

2. **Automated Scanning**
   ```
   Run before commit:
   □ SAST (Static Analysis) - semgrep, CodeQL, bandit
   □ Dependency audit - npm audit, pip-audit
   □ Secret scanning - gitleaks, trufflehog
   ```

3. **Security Unit Tests**
   ```typescript
   describe('Input Validation', () => {
     it('rejects SQL injection attempts', () => {
       const malicious = "'; DROP TABLE users; --";
       expect(() => validateUsername(malicious)).toThrow();
     });

     it('rejects XSS payloads', () => {
       const malicious = '<script>alert(1)</script>';
       expect(() => validateDisplayName(malicious)).toThrow();
     });

     it('enforces length limits', () => {
       const tooLong = 'a'.repeat(10001);
       expect(() => validateBio(tooLong)).toThrow();
     });
   });
   ```

## OWASP Top 10 Quick Reference

| # | Vulnerability | Prevention |
|---|---------------|------------|
| 1 | **Broken Access Control** | Deny by default, verify ownership, server-side checks |
| 2 | **Cryptographic Failures** | TLS everywhere, strong algorithms, no hardcoded secrets |
| 3 | **Injection** | Parameterized queries, input validation, output encoding |
| 4 | **Insecure Design** | Threat modeling, secure design patterns, defense in depth |
| 5 | **Security Misconfiguration** | Secure defaults, minimal permissions, disable unused features |
| 6 | **Vulnerable Components** | Keep updated, audit dependencies, monitor CVEs |
| 7 | **Auth Failures** | MFA, strong passwords, rate limiting, secure sessions |
| 8 | **Data Integrity Failures** | Verify signatures, validate sources, CI/CD security |
| 9 | **Logging Failures** | Log security events, protect logs, monitor alerts |
| 10 | **SSRF** | Allowlist URLs, validate/sanitize, no raw user URLs |

See: [references/owasp-top-10.md](references/owasp-top-10.md)

## Security Checklists

### Pre-Code Checklist

Before writing security-sensitive code:

1. [ ] What data is untrusted? (List all sources)
2. [ ] What's the worst that could happen? (Impact assessment)
3. [ ] How will I validate input? (Specific strategy)
4. [ ] How will I encode output? (Context-specific)
5. [ ] What authentication is required?
6. [ ] What authorization checks are needed?
7. [ ] What should be logged? What should NOT be logged?
8. [ ] What secrets are involved? How are they stored?

### During-Code Checklist

While coding, continuously verify:

1. [ ] Is every user input validated?
2. [ ] Is output encoded for its context?
3. [ ] Are database queries parameterized?
4. [ ] Are authorization checks on the server?
5. [ ] Are secrets out of code? (env vars, secret managers)
6. [ ] Are errors safe? (No stack traces to users)
7. [ ] Is sensitive data encrypted at rest and in transit?
8. [ ] Are dependencies up-to-date and audited?

### Post-Code Checklist

After implementation:

1. [ ] Run SAST scanner (semgrep, CodeQL)
2. [ ] Run dependency audit
3. [ ] Run secret scanner
4. [ ] Test with malicious inputs manually
5. [ ] Verify error messages don't leak info
6. [ ] Check logs don't contain secrets
7. [ ] Review authentication flow end-to-end
8. [ ] Verify authorization at every endpoint
9. [ ] Test as different user roles
10. [ ] Document security controls for reviewers

## Red Flags - STOP and Fix

**Immediate security issues (see references for details):**
- SQL string concatenation with user input
- Setting innerHTML with unsanitized user data
- Dynamic code execution with untrusted data
- Shell command construction with string interpolation
- Hardcoded credentials, API keys, or secrets
- Missing authentication on sensitive endpoints
- Client-side only authorization
- Disabled security features (CSRF, CSP, etc.)
- Sensitive data in URL parameters
- Passwords stored in plaintext or weak hash

**Design smells:**
- "We'll add security later"
- "Users won't do that"
- "It's internal, so it's safe"
- "The framework handles that"
- "We trust this third-party data"

## Language-Specific Guidance

### JavaScript/TypeScript

**XSS Prevention:**
- Use `textContent` instead of `innerHTML` for user data
- Use DOMPurify to sanitize if HTML is required
- Use `Object.hasOwn()` for property checks on user-controlled keys

**Prototype Pollution Prevention:**
- Validate JSON structure before merging
- Use `Object.freeze()` on sensitive objects
- Avoid recursive merge with untrusted data

### Python

**SQL Injection Prevention:**
```python
# ALWAYS use parameterized queries
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
```

**Command Execution:**
```python
# Use subprocess with array args, shell=False
subprocess.run(["ls", user_path], shell=False)
```

**Path Traversal Prevention:**
```python
# Use basename to strip directory components
safe_path = os.path.join("/data", os.path.basename(user_filename))
```

### SQL

```sql
-- Always use parameterized queries via your ORM or driver
-- Never concatenate user input into query strings
-- Limit SELECT to needed fields only
```

## Integration with Other Skills

**Use alongside:**
- **systematic-debugging** - When investigating security issues
- **solid** - Security patterns often follow SOLID principles
- **test-driven-development** - Write security tests first
- **verification-before-completion** - Security verification before claiming done

**Security is not a feature - it's a property of ALL features.**

## Quick Reference Card

```
INPUT:    Validate type, length, format, range, allowlist
OUTPUT:   Encode for context (HTML, URL, SQL, Shell)
AUTH:     Strong passwords, MFA, rate limiting
AUTHZ:    Deny default, check ownership, server-side
SECRETS:  Never in code, use secret managers
ERRORS:   Safe messages, no stack traces, log securely
DEPENDS:  Audit, update, monitor CVEs
ENCRYPT:  TLS in transit, AES at rest, strong algorithms
```

## Remember

> "Security is not a product, but a process." - Bruce Schneier

> "Attackers think in graphs. Defenders think in lists." - John Lambert

Your code will be attacked. Write it assuming the attacker is skilled, patient, and motivated.

---
> Converted and distributed by [TomeVault](https://tomevault.io/claim/xza85hrf) — claim your Tome and manage your conversions.
<!-- tomevault:4.0:skill_md:2026-04-15 -->

