Perform comprehensive security audit of the codebase
Performs comprehensive security audit scanning for common vulnerabilities in React/Next.js apps, including authentication flaws, SQL injection, data exposure, and outdated dependencies.
/plugin marketplace add Tylerbryy/codewarden/plugin install codewarden@codewarden-marketplacePerform a thorough security audit of your application, focusing on common vulnerabilities in React/Next.js applications, Server Actions, API routes, and authentication flows.
When this command is invoked:
Scan for common vulnerabilities:
Server Action Security
Authentication & Authorization
Data Exposure
Input Validation
Dependency Security
Generate security report:
Critical (🔴 Fix Immediately)
High (🟠 Fix Soon)
Medium (🟡 Address)
Low (🔵 Consider)
Provide remediation guidance:
// ❌ BAD: No authentication, no validation
"use server"
export async function deleteUser(userId: string) {
await db.delete(users).where(eq(users.id, userId))
}
// ✅ GOOD: Auth + validation + authorization
"use server"
import { z } from 'zod'
import { auth } from '@/lib/auth'
const schema = z.object({
userId: z.string().uuid()
})
export async function deleteUser(userId: string) {
// 1. Authenticate
const session = await auth()
if (!session?.user) throw new Error('Unauthorized')
// 2. Validate input
const { userId: validId } = schema.parse({ userId })
// 3. Authorize (check ownership/permissions)
if (session.user.role !== 'admin' && session.user.id !== validId) {
throw new Error('Forbidden')
}
// 4. Execute
await db.delete(users).where(eq(users.id, validId))
// 5. Audit log
await logAction('delete_user', { userId: validId, by: session.user.id })
}
// ❌ BAD: Exposing secret in client
"use client"
const apiKey = process.env.SECRET_API_KEY // Exposed in bundle!
// ✅ GOOD: Use on server only
// Server Component or Server Action
const apiKey = process.env.SECRET_API_KEY // Never sent to client
// ✅ GOOD: Public vars explicitly marked
"use client"
const publicKey = process.env.NEXT_PUBLIC_API_KEY // OK to expose
// ❌ BAD: String interpolation = SQL injection
const results = await db.execute(
`SELECT * FROM users WHERE email = '${userInput}'`
)
// ✅ GOOD: Parameterized queries
const results = await db.select()
.from(users)
.where(eq(users.email, userInput))
// ✅ GOOD: Validated input
const schema = z.object({ email: z.string().email() })
const { email } = schema.parse({ email: userInput })
const results = await db.select().from(users).where(eq(users.email, email))
// ❌ BAD: Unescaped user content
<div dangerouslySetInnerHTML={{ __html: userComment }} />
// ✅ GOOD: Sanitize first
import DOMPurify from 'isomorphic-dompurify'
<div dangerouslySetInnerHTML={{
__html: DOMPurify.sanitize(userComment)
}} />
// ✅ BETTER: Avoid dangerouslySetInnerHTML
<div>{userComment}</div> // React escapes automatically
// ✅ GOOD: Rate limit sensitive actions
"use server"
import { Ratelimit } from '@upstash/ratelimit'
const ratelimit = new Ratelimit({
redis: Redis.fromEnv(),
limiter: Ratelimit.slidingWindow(10, '1 h'),
})
export async function sendEmail(formData: FormData) {
const session = await auth()
if (!session?.user) throw new Error('Unauthorized')
const { success } = await ratelimit.limit(session.user.id)
if (!success) {
return { error: 'Too many requests. Try again later.' }
}
// Send email...
}
/security-audit
# Full security audit
/security-audit --server-actions
# Audit Server Actions only
/security-audit --critical-only
# Show only critical issues
/security-audit web/src/app/api
# Audit specific directory
/security-audit --fix
# Auto-fix safe issues (with confirmation)
Generate reports in multiple formats:
security-report.md for documentationsecurity-audit.json for CI/CD integrationCan be run as:
/security-audit