Install
$ agentstack add skill-hlsitechio-claude-skills-security-nextjs-security ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Next.js Security Audit
Audit a Next.js application for framework-specific vulnerabilities. Covers App Router (13+) and Pages Router. Defensive focus.
When this skill applies
- Reviewing Next.js apps for security issues
- Auditing Server Actions, Route Handlers, middleware
- Reviewing environment variable usage (the
NEXT_PUBLIC_trap) - Checking authentication patterns specific to Next.js
- Identifying SSRF in
next/imageconfigurations - Auditing the differences between Server and Client Components
Use other skills for: generic React patterns (react-security), backend services Next calls (nodejs-express-security etc.), auth providers (clerk-security, nextauth-security), Vercel platform settings (vercel-platform-security).
Workflow
Follow ../_shared/audit-workflow.md. Next.js-specific notes below.
Phase 1: Stack detection
- Next.js version (13, 14, 15 — App Router behaviors differ)
- Router model: App Router (
app/), Pages Router (pages/), or hybrid - Deployment target: Vercel, self-hosted Node, edge runtime, static export
- Auth: NextAuth/Auth.js, Clerk, custom JWT, Supabase Auth, other
Phase 2: Inventory
# Layout
find . -name 'next.config.*' -not -path '*/node_modules/*'
find app -type f \( -name 'page.tsx' -o -name 'route.ts' -o -name 'layout.tsx' \) 2>/dev/null | head -20
find pages -type f \( -name '*.tsx' -o -name '*.ts' \) 2>/dev/null | head -20
# Server Actions (App Router)
grep -rn "'use server'" app/ src/ 2>/dev/null | head -50
# Middleware
find . -name 'middleware.ts' -o -name 'middleware.tsx' -o -name 'middleware.js' 2>/dev/null | head
# Environment variable references
grep -rn "process.env" app/ src/ pages/ 2>/dev/null | head -50
# next/image config (image optimization)
grep -n 'images:\|remotePatterns\|domains:' next.config.* 2>/dev/null
Phase 3: Detection — the checks
Environment variables — the NEXT_PUBLIC_ trap
- NXT-ENV-1 Variables prefixed with
NEXT_PUBLIC_are inlined into the client bundle at build time. Anything not strictly public must NOT have this prefix. - NXT-ENV-2 Common mistakes:
NEXT_PUBLIC_STRIPE_SECRET_KEY,NEXT_PUBLIC_DATABASE_URL,NEXT_PUBLIC_API_KEY— all of these have shipped to production at multiple companies. Audit everyNEXT_PUBLIC_for "is this really public?" - NXT-ENV-3 Verify by building and inspecting:
``bash npm run build && \ grep -rhE 'NEXT_PUBLIC_[A-Z_]+' .next/static/chunks/*.js | sort -u # If any NEXT_PUBLIC_*_SECRET or NEXT_PUBLIC_*_KEY values show up, that's a leak ``
- NXT-ENV-4 Server-only secrets read from
process.env.SOMETHING_SECRETonly in server components, server actions, route handlers, orgetServerSideProps/getStaticProps. Never reference them in a Client Component or shared utility imported by both.
Server vs Client Components (App Router)
- NXT-RSC-1 Files with
"use client"are Client Components and ship to the browser; nothing in their import graph can contain secrets. - NXT-RSC-2 Files without
"use client"inapp/are Server Components — they can read secrets but must NOT pass them as props to Client Components (props serialize to the client). - NXT-RSC-3 Use the
server-onlypackage to fail-fast on accidental client imports of server modules:
``ts // lib/db.ts import 'server-only'; export const db = createDbClient(process.env.DATABASE_URL!); `` If any Client Component transitively imports this, the build fails.
- NXT-RSC-4 Use
client-onlysimilarly for browser-only modules.
Server Actions
Server Actions ("use server") are POST endpoints generated by Next, callable from forms or directly from Client Components. They're a common new XSS-equivalent attack surface.
- NXT-SA-1 Every Server Action checks authentication. There's no implicit auth — Next doesn't add one.
```ts 'use server'; import { auth } from '@/lib/auth';
export async function deletePost(postId: string) { const session = await auth(); if (!session?.user) throw new Error('Unauthorized'); // ... and check the user owns the post } ```
- NXT-SA-2 Server Actions check authorization on the specific resource — not just "is user authenticated" but "does user own/have-access-to this object".
- NXT-SA-3 Input validated with Zod or similar; never trust the shape of the FormData / serialized args.
- NXT-SA-4 Server Actions don't accept
userId/tenantIdas args — derive from session. - NXT-SA-5 Mutation Server Actions handle CSRF correctly. Next has built-in protection for Server Actions called via form submission with the same-origin policy, but custom invocations need verification.
- NXT-SA-6 Server Actions that perform sensitive operations have rate limiting (no built-in; use a Redis/Upstash counter).
Route Handlers (App Router) and API Routes (Pages Router)
- NXT-RH-1 Every Route Handler in
app/.../route.tsand every API route inpages/api/checks auth. - NXT-RH-2 No accidental data exposure — handlers return only what the caller is authorized to see.
- NXT-RH-3 CORS configured per handler when needed; not globally permissive.
- NXT-RH-4 Webhook receivers (Stripe, Resend, etc.) verify signatures — see
saas-security-pack/saas-api-security/references/webhook-security.md. - NXT-RH-5 Catch-all routes (
[...slug]/route.ts) validate the captured path; common path traversal vector.
Middleware
middleware.ts runs before every matched request — a powerful place to enforce, also a powerful place to introduce bugs.
- NXT-MW-1 Middleware that performs auth checks: ensure it's actually applied to the routes you think (the
config.matcherfield). - NXT-MW-2 Middleware running on the Edge runtime can't use Node.js APIs; if you need
cryptofor HMAC, use the Web Crypto API. - NXT-MW-3 Middleware doesn't leak: don't put sensitive headers, cookies, or info-disclosure into rewrites/responses from middleware.
- NXT-MW-4 Middleware should not be the only auth check — it's easy to misconfigure matcher and route around. Server Actions / Route Handlers still check.
- NXT-MW-5
request.headers.get('x-forwarded-for')and similar are spoofable client-side except behind a properly-configured reverse proxy. Don't use for security decisions without verifying the proxy chain.
Image Optimization SSRF
next/image can fetch from any URL listed in images.remotePatterns / images.domains in next.config.js and proxy through your server. Bad configs become SSRF.
- NXT-IMG-1
images.remotePatternslists specific hostnames; no wildcards like**. - NXT-IMG-2 No legacy
images.domains: ['*']config. - NXT-IMG-3 Self-hosted Next.js: image optimizer can fetch internal IPs unless restricted. The Vercel-hosted version blocks RFC1918; self-hosted defaults more permissive.
- NXT-IMG-4 If users can supply image URLs (avatars, embeds), the URLs go through
next/imagewhich proxies through your server — making your server the source IP for the fetch. Validate URLs before passing to next/image.
// BAD
module.exports = {
images: {
remotePatterns: [{ protocol: 'https', hostname: '**' }], // any host
},
};
// GOOD
module.exports = {
images: {
remotePatterns: [
{ protocol: 'https', hostname: 'images.yourcdn.com' },
{ protocol: 'https', hostname: '*.s3.amazonaws.com', pathname: '/yourbucket/**' },
],
},
};
Session and auth handling
- NXT-AUTH-1 Session cookies follow the patterns in
saas-security-pack/saas-frontend-hardening/references/cookie-config.md. - NXT-AUTH-2 If using NextAuth: see
nextauth-securityskill. - NXT-AUTH-3 If using Clerk: see
clerk-securityskill. - NXT-AUTH-4 Custom JWT: validate signature on every request; rotate JWT secret periodically; see
saas-security-pack/saas-code-security-review/references/jwt-validation.md. - NXT-AUTH-5 Login redirect URLs validated against allowlist (open redirect via
callbackUrl=...).
Static export vs runtime
- NXT-EXP-1 Static-exported pages don't run server logic at request time; auth checks intended to run server-side don't. Confirm the deployment mode matches the security model.
next.config.js security flags
- NXT-CFG-1
headers()configured to add CSP, HSTS, X-Content-Type-Options, etc. (seesaas-security-pack/saas-frontend-hardening). - NXT-CFG-2
poweredByHeader: false(removesX-Powered-By: Next.js— info disclosure). - NXT-CFG-3
reactStrictMode: true— not strictly security, but surfaces hydration mismatches that can have security implications. - NXT-CFG-4 Custom redirect / rewrite rules don't accept user-controllable targets without validation (open redirect).
Dependency hygiene
- NXT-DEP-1 Next.js version is a recently-patched release. Several Next.js versions have had Critical CVEs:
- CVE-2024-46982 (cache poisoning on Pages Router)
- CVE-2024-34351 (SSRF via Server Actions)
- CVE-2025-29927 (middleware bypass — fixed in 14.2.25 / 15.2.3)
- older CVEs in 13.x
Pin to the latest patch of your supported major; review release notes for security fixes.
Phase 4: Triage
Critical class examples:
NEXT_PUBLIC_*_SECRETenv vars (definitive client leak)- Server Action without auth check performing sensitive ops
- Middleware-only auth bypassable via specific URL pattern (see CVE-2025-29927 class)
- next/image with wildcard remote patterns
- Server Component passing secret-bearing prop to Client Component
Phase 5: Report
Use ../_shared/findings-schema.md. Prefix IDs with NXT-.
References
references/app-router-patterns.md— Server Actions, RSC, middleware patterns and pitfalls
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: hlsitechio
- Source: hlsitechio/claude-skills-security
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.