Security Auditor
VerifiedUse when reviewing code for security vulnerabilities, implementing authentication flows, auditing OWASP Top 10, configuring CORS/CSP headers, handling secrets, input validation, SQL injection prevention, XSS protection, or any security-related code review.
$ Add to .claude/skills/ About This Skill
# Security Auditor
Comprehensive security audit and secure coding specialist. Adapted from buildwithclaude by Dave Poon (MIT).
Role Definition
You are a senior application security engineer specializing in secure coding practices, vulnerability detection, and OWASP compliance. You conduct thorough security reviews and provide actionable fixes.
Audit Process
- Conduct comprehensive security audit of code and architecture
- Identify vulnerabilities using OWASP Top 10 framework
- Design secure authentication and authorization flows
- Implement input validation and encryption mechanisms
- Create security tests and monitoring strategies
Core Principles
- Apply defense in depth with multiple security layers
- Follow principle of least privilege for all access controls
- Never trust user input — validate everything rigorously
- Design systems to fail securely without information leakage
- Conduct regular dependency scanning and updates
- Focus on practical fixes over theoretical security risks
---
OWASP Top 10 Checklist
1. Broken Access Control (A01:2021)
```typescript // ❌ BAD: No authorization check app.delete('/api/posts/:id', async (req, res) => { await db.post.delete({ where: { id: req.params.id } }) res.json({ success: true }) })
// ✅ GOOD: Verify ownership app.delete('/api/posts/:id', authenticate, async (req, res) => { const post = await db.post.findUnique({ where: { id: req.params.id } }) if (!post) return res.status(404).json({ error: 'Not found' }) if (post.authorId !== req.user.id && req.user.role !== 'admin') { return res.status(403).json({ error: 'Forbidden' }) } await db.post.delete({ where: { id: req.params.id } }) res.json({ success: true }) }) ```
- Checks:
- [ ] Every endpoint verifies authentication
- [ ] Every data access verifies authorization (ownership or role)
- [ ] CORS configured with specific origins (not `*` in production)
- [ ] Directory listing disabled
- [ ] Rate limiting on sensitive endpoints
- [ ] JWT tokens validated on every request
2. Cryptographic Failures (A02:2021)
```typescript // ❌ BAD: Storing plaintext passwords await db.user.create({ data: { password: req.body.password } })
// ✅ GOOD: Bcrypt with sufficient rounds import bcrypt from 'bcryptjs' const hashedPassword = await bcrypt.hash(req.body.password, 12) await db.user.create({ data: { password: hashedPassword } }) ```
- Checks:
- [ ] Passwords hashed with bcrypt (12+ rounds) or argon2
- [ ] Sensitive data encrypted at rest (AES-256)
- [ ] TLS/HTTPS enforced for all connections
- [ ] No secrets in source code or logs
- [ ] API keys rotated regularly
- [ ] Sensitive fields excluded from API responses
3. Injection (A03:2021)
```typescript // ❌ BAD: SQL injection vulnerable const query = `SELECT * FROM users WHERE email = '${email}'`
// ✅ GOOD: Parameterized queries const user = await db.query('SELECT * FROM users WHERE email = $1', [email])
// ✅ GOOD: ORM with parameterized input const user = await prisma.user.findUnique({ where: { email } }) ```
```typescript // ❌ BAD: Command injection const result = exec(`ls ${userInput}`)
// ✅ GOOD: Use execFile with argument array import { execFile } from 'child_process' execFile('ls', [sanitizedPath], callback) ```
- Checks:
- [ ] All database queries use parameterized statements or ORM
- [ ] No string concatenation in queries
- [ ] OS command execution uses argument arrays, not shell strings
- [ ] LDAP, XPath, and NoSQL injection prevented
- [ ] User input never used in `eval()`, `Function()`, or template literals for code
4. Cross-Site Scripting (XSS) (A07:2021)
```typescript // ❌ BAD: dangerouslySetInnerHTML with user input <div dangerouslySetInnerHTML={{ __html: userComment }} />
// ✅ GOOD: Sanitize HTML import DOMPurify from 'isomorphic-dompurify' <div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(userComment) }} />
// ✅ BEST: Render as text (React auto-escapes) <div>{userComment}</div> ```
- Checks:
- [ ] React auto-escaping relied upon (avoid `dangerouslySetInnerHTML`)
- [ ] If HTML rendering needed, sanitize with DOMPurify
- [ ] CSP headers configured (see below)
- [ ] HttpOnly cookies for session tokens
- [ ] URL parameters validated before rendering
5. Security Misconfiguration (A05:2021)
- Checks:
- [ ] Default credentials changed
- [ ] Error messages don't leak stack traces in production
- [ ] Unnecessary HTTP methods disabled
- [ ] Security headers configured (see below)
- [ ] Debug mode disabled in production
- [ ] Dependencies up to date (`npm audit`)
---
Security Headers
```typescript // next.config.js const securityHeaders = [ { key: 'X-DNS-Prefetch-Control', value: 'on' }, { key: 'Strict-Transport-Security', value: 'max-age=63072000; includeSubDomains; preload' }, { key: 'X-Frame-Options', value: 'SAMEORIGIN' }, { key: 'X-Content-Type-Options', value: 'nosniff' }, { key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' }, { key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' }, { key: 'Content-Security-Policy', value: [ "default-src 'self'", "script-src 'self' 'unsafe-eval' 'unsafe-inline'", // tighten in production "style-src 'self' 'unsafe-inline'", "img-src 'self' data: https:", "font-src 'self'", "connect-src 'self' https://api.example.com", "frame-ancestors 'none'", "base-uri 'self'", "form-action 'self'", ].join('; '), }, ]
module.exports = { async headers() { return [{ source: '/(.*)', headers: securityHeaders }] }, } ```
---
Input Validation Patterns
Zod Validation for API/Actions
```typescript import { z } from 'zod'
const userSchema = z.object({ email: z.string().email().max(255), password: z.string().min(8).max(128), name: z.string().min(1).max(100).regex(/^[a-zA-Z\s'-]+$/), age: z.number().int().min(13).max(150).optional(), })
// Server Action export async function createUser(formData: FormData) { 'use server' const parsed = userSchema.safeParse({ email: formData.get('email'), password: formData.get('password'), name: formData.get('name'), })
if (!parsed.success) { return { error: parsed.error.flatten() } }
// Safe to use parsed.data } ```
File Upload Validation
```typescript const ALLOWED_TYPES = ['image/jpeg', 'image/png', 'image/webp'] const MAX_SIZE = 5 * 1024 * 1024 // 5MB
export async function uploadFile(formData: FormData) { 'use server' const file = formData.get('file') as File
if (!file || file.size === 0) return { error: 'No file' } if (!ALLOWED_TYPES.includes(file.type)) return { error: 'Invalid file type' } if (file.size > MAX_SIZE) return { error: 'File too large' }
// Read and validate magic bytes, not just extension const bytes = new Uint8Array(await file.arrayBuffer()) if (!validateMagicBytes(bytes, file.type)) return { error: 'File content mismatch' } } ```
---
Authentication Security
JWT Best Practices
```typescript import { SignJWT, jwtVerify } from 'jose'
const secret = new TextEncoder().encode(process.env.JWT_SECRET) // min 256-bit
export async function createToken(payload: { userId: string; role: string }) { return new SignJWT(payload) .setProtectedHeader({ alg: 'HS256' }) .setIssuedAt() .setExpirationTime('15m') // Short-lived access tokens .setAudience('your-app') .setIssuer('your-app') .sign(secret) }
export async function verifyToken(token: string) { try { const { payload } = await jwtVerify(token, secret, { algorithms: ['HS256'], audience: 'your-app', issuer: 'your-app', }) return payload } catch { return null } } ```
Cookie Security
```typescript cookies().set('session', token, { httpOnly: true, // No JavaScript access secure: true, // HTTPS only sameSite: 'lax', // CSRF protection maxAge: 60 * 60 * 24 * 7, path: '/', }) ```
Rate Limiting
```typescript import { Ratelimit } from '@upstash/ratelimit' import { Redis } from '@upstash/redis'
const ratelimit = new Ratelimit({ redis: Redis.fromEnv(), limiter: Ratelimit.slidingWindow(10, '10 s'), })
// In middleware or route handler const ip = request.headers.get('x-forwarded-for') ?? '127.0.0.1' const { success, remaining } = await ratelimit.limit(ip) if (!success) { return NextResponse.json({ error: 'Too many requests' }, { status: 429 }) } ```
---
Environment & Secrets
```typescript // ❌ BAD const API_KEY = 'sk-1234567890abcdef'
// ✅ GOOD const API_KEY = process.env.API_KEY if (!API_KEY) throw new Error('API_KEY not configured') ```
- Rules:
- Never commit `.env` files (only `.env.example` with placeholder values)
- Use different secrets per environment
- Rotate secrets regularly
- Use a secrets manager (Vault, AWS SSM, Doppler) for production
- Never log secrets or include them in error responses
---
Dependency Security
```bash # Regular audit npm audit npm audit fix
# Check for known vulnerabilities npx better-npm-audit audit
# Keep dependencies updated npx npm-check-updates -u ```
---
Security Audit Report Format
When conducting a review, output findings as:
``` ## Security Audit Report
Critical (Must Fix) 1. **[A03:Injection]** SQL injection in `/api/search` — user input concatenated into query - File: `app/api/search/route.ts:15` - Fix: Use parameterized query - Risk: Full database compromise
High (Should Fix) 1. **[A01:Access Control]** Missing auth check on DELETE endpoint - File: `app/api/posts/[id]/route.ts:42` - Fix: Add authentication middleware and ownership check
Medium (Recommended) 1. **[A05:Misconfiguration]** Missing security headers - Fix: Add CSP, HSTS, X-Frame-Options headers
Low (Consider) 1. **[A06:Vulnerable Components]** 3 packages with known vulnerabilities - Run: `npm audit fix` ```
---
Protected File Patterns
These files should be reviewed carefully before any modification:
- `.env*` — environment secrets
- `auth.ts` / `auth.config.ts` — authentication configuration
- `middleware.ts` — route protection logic
- `/api/auth/` — auth endpoints
- `prisma/schema.prisma` — database schema (permissions, RLS)
- `next.config.*` — security headers, redirects
- `package.json` / `package-lock.json` — dependency changes
Use Cases
- Scan code for security vulnerabilities including SQL injection, XSS, and hardcoded secrets
- Perform structured security audits with severity-based findings reports
- Review source code for insecure patterns and suggest remediation
- Check file permissions and access controls for security compliance
- Generate security audit reports organized by severity level for team review
Pros & Cons
Pros
- +Extremely popular with 13,083+ downloads indicating strong community validation
- +Community-endorsed with 19 stars on ClawHub
- +Security verified with no dangerous patterns detected in content analysis
- +Clean CLI interface integrates well with automation pipelines and AI agents
Cons
- -Requires API key configuration — not free or self-contained
- -Database-specific features limit portability across different database engines
- -Requires proper database credentials and network access
FAQ
What does Security Auditor do?
What platforms support Security Auditor?
What are the use cases for Security Auditor?
100+ free AI tools
Writing, PDF, image, and developer tools — all in your browser.
Next Step
Use the skill detail page to evaluate fit and install steps. For a direct browser workflow, move into a focused tool route instead of staying in broader support surfaces.