---
name: nextjs-security-audit
description: "Audit a Next.js change across the full web-app attack surface before it ships: access control, injection, XSS and output handling, secret exposure, and dangerous config. Use before shipping any Server Action, Route Handler, form, data flow, or next.config change. Next.js protects a real slice for you (server isolation, encrypted action IDs, a CSRF baseline), but every action and handler is still a public POST endpoint. This checks auth and ownership, SQL injection, dangerouslySetInnerHTML, SSRF, mass assignment, leaked secrets, missing security headers, and more, each flagged for review, not blindly certified."
---

# Next.js Security Audit

The security pass before you ship: auth and ownership, injection, XSS, SSRF, secret leaks, and missing headers. It flags what a grep can catch and hands you a review checklist for the rest, because a scanner cannot certify that your authorization is correct.

## Phases

Work through these in order.

### 1. Scan

Run the scanner over the changed files to flag the mechanically-detectable risks (leaked secrets, interpolated SQL, dangerouslySetInnerHTML, fetch to a user URL, spread request bodies, missing security headers, dangerous image config) for review.

Read: [security](https://selwynuy.dev/d/security.md), [environment-and-secrets](https://selwynuy.dev/d/environment-and-secrets.md)

### 2. Access control

For every Server Action and Route Handler, confirm it re-checks authentication itself (a page check does not cover it), checks resource ownership to stop IDOR, validates client input, and rate limits anything expensive or abusable.

Read: [security-by-design](https://selwynuy.dev/d/security-by-design.md), [authentication](https://selwynuy.dev/d/authentication.md), [rate-limiting](https://selwynuy.dev/d/rate-limiting.md)

### 3. Injection and output

Confirm queries are parameterized (never string-built), user HTML is sanitized before dangerouslySetInnerHTML, redirects and outbound fetches are allowlisted (open redirect, SSRF), and no request body is spread into a database write.

Read: [security](https://selwynuy.dev/d/security.md), [data-security](https://selwynuy.dev/d/data-security.md)

### 4. Exposure and config

Confirm secrets stay server-only (no NEXT_PUBLIC_, process.env only in the data layer), only minimal DTOs cross to the client, errors do not leak stack traces, security headers are set, and next.config has no dangerous image options.

Read: [environment-and-secrets](https://selwynuy.dev/d/environment-and-secrets.md), [data-security](https://selwynuy.dev/d/data-security.md), [content-security-policy](https://selwynuy.dev/d/content-security-policy.md)

## Bundled files

- `scripts/scan-security.mjs` (script): Greps the changed files for the high-confidence risk patterns across every vuln family and flags each for human review. It surfaces risks; it does not certify that the code is safe.
- `references/security-audit-checklist.md` (reference): The full web-app audit: what Next.js protects by default versus what you own, every vuln class with its detection signal and fix, sourced to the framework's bundled docs and the handbook.

---

Part of Next.js Security Audit from Selwyn Uy's Next.js Handbook. Full page: https://selwynuy.dev/skills/nextjs-security-audit
