# Security Reviewer

> Comprehensive application security reviewer for web apps, mobile apps, APIs, and infrastructure. Runs automated scans (Semgrep SAST, Gitleaks secrets, npm/pip audit, dependency checks) and manual code review against OWASP Top 10, CWE Top 25, STRIDE threat model, and SLSA compliance. Use when: reviewing code for vulnerabilities, scanning for exposed secrets/API keys, auditing dependencies, checking security headers, conducting threat modeling, performing pre-deployment security checks, or running end-of-session security sweeps. Triggers on: security review, vulnerability scan, secret detection, dependency audit, penetration test prep, compliance check, threat model, security assessment.

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

---


# Security Reviewer - Application Security Intelligence

Comprehensive security review system for web apps, mobile apps, APIs, and infrastructure. Combines automated scanning tools with expert manual review against industry frameworks.

## When to Use

**Must Use (automatic triggers):**
- Before any deployment or push to production
- End of development session (security sweep)
- After adding new dependencies
- After implementing auth/payment/data-handling features
- When handling user input, file uploads, or external data
- When configuring CORS, CSP, or other security headers
- When reviewing PRs that touch security-sensitive code

**Recommended:**
- After significant refactoring
- When onboarding new APIs or third-party services
- Periodic codebase health checks
- Before security audits or compliance reviews

## Automated Scanning Tools

### 1. Semgrep (SAST - Static Analysis)
Scans code for vulnerability patterns across 30+ languages.

```bash
# Full project scan with auto-detection
semgrep scan --config auto .
# Windows/MINGW fallback: python -m semgrep scan --config auto .

# Scan specific OWASP categories
semgrep scan --config "p/owasp-top-ten" .

# Scan for secrets in code
semgrep scan --config "p/secrets" .

# Scan for specific language
semgrep scan --config "p/javascript" .
semgrep scan --config "p/python" .
semgrep scan --config "p/typescript" .
semgrep scan --config "p/react" .

# Scan with JSON output for parsing
semgrep scan --config auto --json .

# Scan specific files
semgrep scan --config auto src/auth/ src/api/
```

**Key rulesets:**
- `p/owasp-top-ten` — OWASP Top 10 vulnerabilities
- `p/secrets` — Hardcoded secrets and credentials
- `p/security-audit` — Broad security patterns
- `p/javascript` / `p/typescript` / `p/python` / `p/react` — Language-specific
- `p/jwt` — JWT implementation issues
- `p/sql-injection` — SQL injection patterns
- `p/xss` — Cross-site scripting patterns

### 2. Gitleaks (Secret Detection)
Scans git history and working directory for exposed secrets.

```bash
# Scan current directory
gitleaks detect -s . -v

# Scan git history
gitleaks detect -v

# Generate JSON report
gitleaks detect -s . -f json -r gitleaks-report.json

# Scan specific path
gitleaks detect -s ./src -v
```

### 3. npm audit (JavaScript Dependencies)
```bash
# Check for known vulnerabilities
npm audit

# JSON output for parsing
npm audit --json

# Fix automatically where possible
npm audit fix

# Check production deps only
npm audit --omit=dev
```

### 4. pip-audit (Python Dependencies)
```bash
# Scan current environment
pip-audit
# Windows/MINGW fallback: python -m pip_audit

# Scan requirements file
pip-audit -r requirements.txt
# Windows/MINGW fallback: python -m pip_audit -r requirements.txt

# JSON output
pip-audit --format json

# Fix automatically
pip-audit --fix
```

### 5. GitHub Security Features (via gh CLI)
```bash
# Check Dependabot alerts
gh api repos/{owner}/{repo}/dependabot/alerts --jq '.[].security_advisory.summary'

# Check secret scanning alerts
gh api repos/{owner}/{repo}/secret-scanning/alerts --jq '.[].secret_type_display_name'

# Check code scanning alerts
gh api repos/{owner}/{repo}/code-scanning/alerts --jq '.[].rule.description'
```

### 6. Manual Pattern Scanning (via Grep)
When automated tools aren't available, use Grep for critical patterns:

```bash
# Hardcoded secrets patterns
grep -rn "api[_-]?key\s*[:=]" --include="*.{js,ts,py,env}" .
grep -rn "password\s*[:=]\s*['\"]" --include="*.{js,ts,py}" .
grep -rn "secret\s*[:=]\s*['\"]" --include="*.{js,ts,py}" .
grep -rn "token\s*[:=]\s*['\"]" --include="*.{js,ts,py}" .
grep -rn "AKIA[0-9A-Z]{16}" .  # AWS Access Keys
grep -rn "sk-[a-zA-Z0-9]{48}" .  # OpenAI API keys
grep -rn "ghp_[a-zA-Z0-9]{36}" .  # GitHub tokens

# SQL injection patterns
grep -rn "execute.*f['\"]" --include="*.py" .
grep -rn "query.*\$\{" --include="*.{js,ts}" .
grep -rn "raw\(.*\+" --include="*.{js,ts,py}" .

# XSS patterns
grep -rn "dangerouslySetInnerHTML" --include="*.{jsx,tsx}" .
grep -rn "innerHTML\s*=" --include="*.{js,ts}" .
grep -rn "document\.write" --include="*.{js,ts}" .
grep -rn "\|safe" --include="*.html" .  # Django/Jinja unsafe filter

# Insecure configurations
grep -rn "cors.*origin.*\*" --include="*.{js,ts}" .
grep -rn "verify.*false" --include="*.{js,ts,py}" .
grep -rn "rejectUnauthorized.*false" --include="*.{js,ts}" .
grep -rn "disable.*csrf" --include="*.{js,ts,py}" .
grep -rn "NODE_TLS_REJECT_UNAUTHORIZED" --include="*.{js,ts}" .
```

## Security Review Frameworks

### OWASP Top 10 (2021) — Deep Checklist

#### A01: Broken Access Control
- [ ] Authorization checked server-side on every request (not just client-side)
- [ ] Deny by default — users can only access their own data
- [ ] CORS allowlists specific origins (never wildcard `*` in production)
- [ ] Directory traversal prevented (no `../` in file paths)
- [ ] JWT tokens validated: signature, expiry, issuer, audience
- [ ] Rate limiting on sensitive endpoints (login, password reset, API)
- [ ] IDOR (Insecure Direct Object Reference) — verify user owns resource
- [ ] Admin endpoints require role check, not just authentication
- [ ] API keys scoped to minimum required permissions

#### A02: Cryptographic Failures
- [ ] TLS 1.2+ enforced for all connections
- [ ] Sensitive data encrypted at rest (AES-256-GCM or ChaCha20)
- [ ] Passwords hashed with bcrypt (cost 12+), argon2id, or scrypt
- [ ] No MD5/SHA1 for password hashing
- [ ] Encryption keys stored in env vars or key management service (not code)
- [ ] PII identified and classified (GDPR/CCPA compliance)
- [ ] No sensitive data in URL query parameters
- [ ] Secure random number generation (`crypto.randomBytes`, not `Math.random`)

#### A03: Injection
- [ ] All SQL uses parameterized queries or ORM — no string concatenation
- [ ] NoSQL injection prevented (MongoDB `$where`, `$gt` operator attacks)
- [ ] Command injection prevented (no `exec(user_input)`, no `shell=True`)
- [ ] LDAP injection prevented
- [ ] XSS prevented: output encoding on all user-supplied data
- [ ] Template injection prevented (server-side template engines)
- [ ] Path traversal prevented on file operations
- [ ] GraphQL query depth limited to prevent DoS

#### A04: Insecure Design
- [ ] Threat model exists (STRIDE analysis)
- [ ] Business logic abuse cases identified
- [ ] Rate limiting on resource-intensive operations
- [ ] Account enumeration prevented (same response for valid/invalid users)
- [ ] Password reset tokens are single-use and time-limited
- [ ] Multi-step flows cannot be bypassed by skipping steps

#### A05: Security Misconfiguration
- [ ] Default credentials changed/removed
- [ ] Debug mode disabled in production
- [ ] Stack traces hidden from users
- [ ] Unnecessary HTTP methods disabled
- [ ] Directory listing disabled
- [ ] Security headers configured (see Security Headers section)
- [ ] Error messages generic — no internal details leaked
- [ ] `.env` files in `.gitignore`
- [ ] Source maps disabled in production

#### A06: Vulnerable & Outdated Components
- [ ] No known CVEs in dependencies (`npm audit` / `pip-audit`)
- [ ] Dependencies pinned to specific versions (lockfile)
- [ ] Unused dependencies removed
- [ ] License compatibility verified
- [ ] Dependabot or similar automated updates configured

#### A07: Identification & Authentication Failures
- [ ] Passwords minimum 8 chars, complexity not over-restrictive
- [ ] Account lockout after 5-10 failed attempts (with exponential backoff)
- [ ] MFA available for sensitive accounts
- [ ] Session tokens regenerated after login
- [ ] Session expiration configured (idle + absolute timeout)
- [ ] Logout invalidates server-side session
- [ ] Password reset doesn't reveal if account exists
- [ ] OAuth state parameter validated (CSRF protection)

#### A08: Software & Data Integrity Failures
- [ ] CI/CD pipeline access restricted
- [ ] Dependencies fetched from trusted registries only
- [ ] Subresource Integrity (SRI) for CDN scripts
- [ ] Code review required before merge
- [ ] Deployment artifacts signed/verified
- [ ] Auto-update mechanism validates signatures

#### A09: Security Logging & Monitoring Failures
- [ ] Authentication events logged (success + failure)
- [ ] Authorization failures logged
- [ ] Input validation failures logged
- [ ] Logs contain timestamp, source IP, user ID, action
- [ ] Logs do NOT contain passwords, tokens, PII, or credit cards
- [ ] Logs protected from injection (structured logging)
- [ ] Alerting configured for anomalous patterns
- [ ] Log retention policy defined

#### A10: Server-Side Request Forgery (SSRF)
- [ ] User-supplied URLs validated against allowlist
- [ ] Internal network access blocked for user-supplied URLs
- [ ] DNS rebinding protection
- [ ] Response from fetched URLs not directly returned to user
- [ ] Cloud metadata endpoints blocked (169.254.169.254)

### CWE Top 25 Additional Checks
- [ ] CWE-787: Out-of-bounds write (buffer overflow)
- [ ] CWE-79: XSS (reflected, stored, DOM-based)
- [ ] CWE-89: SQL injection
- [ ] CWE-416: Use after free
- [ ] CWE-78: OS command injection
- [ ] CWE-20: Improper input validation
- [ ] CWE-125: Out-of-bounds read
- [ ] CWE-22: Path traversal
- [ ] CWE-352: CSRF
- [ ] CWE-434: Unrestricted file upload
- [ ] CWE-862: Missing authorization
- [ ] CWE-476: NULL pointer dereference
- [ ] CWE-287: Improper authentication
- [ ] CWE-190: Integer overflow
- [ ] CWE-502: Deserialization of untrusted data

### STRIDE Threat Model

| Threat | Question | Mitigations |
|--------|----------|-------------|
| **S**poofing | Can an attacker impersonate a user or service? | Strong auth, MFA, certificate pinning |
| **T**ampering | Can data be modified in transit or at rest? | HMAC, digital signatures, TLS, integrity checks |
| **R**epudiation | Can actions be denied without proof? | Audit logging, timestamps, non-repudiation |
| **I**nformation Disclosure | Can sensitive data leak? | Encryption, access control, data classification |
| **D**enial of Service | Can the service be disrupted? | Rate limiting, CDN, input validation, resource limits |
| **E**levation of Privilege | Can permissions be escalated? | Least privilege, role checks, input validation |

### Security Headers (Required)

```
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'; connect-src 'self' https:; frame-ancestors 'none'
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
X-XSS-Protection: 0
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=()
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Resource-Policy: same-origin
```

### SLSA Compliance

| Level | Requirements |
|-------|-------------|
| **L1** | Build process documented, build scripts versioned, provenance generated |
| **L2** | Hosted build service, signed provenance, source version controlled |
| **L3** | Isolated build environment, non-falsifiable provenance, verified source |
| **L4** | Hermetic builds, two-person review, reproducible builds |

## Security Review Workflow

### Phase 1: Automated Scans (run these first)
```bash
# 1. Secret scan
gitleaks detect -s . -v

# 2. SAST scan
semgrep scan --config auto .

# 3. Dependency audit (pick based on stack)
npm audit                    # JavaScript
pip-audit                    # Python
```

### Phase 2: Manual Code Review
1. Read auth/login/session code line by line
2. Check all user input handling
3. Review database query construction
4. Verify file upload restrictions
5. Check API endpoint authorization
6. Review error handling for info leaks
7. Verify environment variable usage (no hardcoded secrets)

### Phase 3: Configuration Review
1. Check `.env.example` exists with placeholder values
2. Verify `.env` is in `.gitignore`
3. Review CORS configuration
4. Check CSP headers
5. Verify production environment disables debug mode
6. Check Dockerfile for security best practices

### Phase 4: Live Testing (if deployed)
1. Test security headers with Playwright
2. Verify HTTPS redirect
3. Test rate limiting
4. Check error pages don't leak info
5. Test auth flows for bypasses

## Vulnerability Report Template

```markdown
# Security Review Report
**Project:** [name]
**Date:** [date]
**Reviewer:** Security Agent

## Executive Summary
[1-2 sentence overall assessment]

## Scan Results
### Semgrep SAST: [X findings]
### Gitleaks Secrets: [X findings]
### Dependency Audit: [X vulnerabilities]

## Findings

### [CRITICAL/HIGH/MEDIUM/LOW] — [Title]
- **CWE:** CWE-XXX
- **OWASP:** A0X
- **Location:** `file:line`
- **Description:** [what's wrong]
- **Impact:** [what an attacker could do]
- **Fix:** [exact code change needed]

## Recommendations
1. [Priority action items]
```

## Secure Coding Quick Reference

### Never Do This
```javascript
// SQL injection
db.query(`SELECT * FROM users WHERE id = ${req.params.id}`)

// Command injection
exec(`convert ${userFile} output.pdf`)

// XSS
element.innerHTML = userInput

// Hardcoded secret
const API_KEY = "sk-abc123..."

// Insecure comparison
if (token == expectedToken)  // use === or crypto.timingSafeEqual

// Logging secrets
console.log("Auth token:", token)
```

### Always Do This
```javascript
// Parameterized query
db.query('SELECT * FROM users WHERE id = $1', [req.params.id])

// Safe command execution
execFile('convert', [sanitizedFile, 'output.pdf'])

// Safe rendering
element.textContent = userInput

// Environment variable
const API_KEY = process.env.API_KEY

// Timing-safe comparison
crypto.timingSafeEqual(Buffer.from(token), Buffer.from(expectedToken))

// Structured logging without secrets
logger.info('Auth attempt', { userId, success: true })
```

