AgentSkillsCN

security-review

当需要运行交互式CLI工具(如vim、git rebase -i、Python REPL等)且这些工具需要实时输入与输出时,可使用此技能。它提供基于tmux的方案,帮助您更好地掌控交互式会话。

SKILL.md
--- frontmatter
name: security-review
description: 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.

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

code
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

    code
    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

    code
    List every:
    ├── Public endpoint
    ├── Input field
    ├── File upload
    ├── API parameter
    ├── Authentication point
    └── Authorization check
    
  3. STRIDE Threat Modeling

    ThreatQuestionExample
    SpoofingCan attacker pretend to be someone else?Session hijacking
    TamperingCan attacker modify data?Parameter manipulation
    RepudiationCan attacker deny actions?Missing audit logs
    Information DisclosureCan attacker access secrets?Error message leaks
    Denial of ServiceCan attacker crash/slow system?Resource exhaustion
    Elevation of PrivilegeCan attacker gain higher access?Broken access control

See: references/threat-modeling.md

Phase 2: Secure Implementation

Apply defense-in-depth at every layer:

Input Validation (First Line of Defense)

code
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)

code
ENCODE FOR CONTEXT:

HTML body    → HTML entity encoding (< > &)
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

code
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

code
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

Phase 3: Verification

Verify security controls are effective:

  1. Manual Testing

    code
    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

    code
    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

#VulnerabilityPrevention
1Broken Access ControlDeny by default, verify ownership, server-side checks
2Cryptographic FailuresTLS everywhere, strong algorithms, no hardcoded secrets
3InjectionParameterized queries, input validation, output encoding
4Insecure DesignThreat modeling, secure design patterns, defense in depth
5Security MisconfigurationSecure defaults, minimal permissions, disable unused features
6Vulnerable ComponentsKeep updated, audit dependencies, monitor CVEs
7Auth FailuresMFA, strong passwords, rate limiting, secure sessions
8Data Integrity FailuresVerify signatures, validate sources, CI/CD security
9Logging FailuresLog security events, protect logs, monitor alerts
10SSRFAllowlist URLs, validate/sanitize, no raw user URLs

See: 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

code
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.