agentsclimarketplace

Nextjs security

Skill hlsitechio/claude-skills-security/appsec-stack-pack/nextjs-security

Security audit specific to Next.js applications including App Router and Pages Router, Server Actions, middleware, Route Handlers, Server Components, environment variable exposure (NEXT_PUBLIC_), getServerSideProps/getStaticProps secret leakage, Image Optimization SSRF, and Next.js-specific authentication patterns. Use this skill whenever the user mentions Next.js, App Router, Pages Router, Server Actions, RSC, server components, middleware.ts, route handlers, NEXT_PUBLIC_, Vercel deployment patterns, next.config.js, or asks "audit my Next.js app", "is my middleware safe", "Server Actions security", "Next.js auth review". Trigger when the codebase contains a `next.config.js`/`next.config.mjs`/`next.config.ts` file, `app/` directory with `page.tsx` files, or `pages/` directory with Next.js conventions.From its SKILL.md

Install
npx -y skills add hlsitechio/claude-skills-security --skill nextjs-security

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

3 things to look at

  • reads credentialsReads from 2 credential sources: `process.env.SOMETHING_SECRET` and 1 more.
  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
  • runs commandsInstructs the agent to run 8 commands, including `find . -name 'next.config.*' -not -path '*/node_modules/*'` and 7 more.

SKILL.md

10.4 KB, ~2.5k tokens by cl100k_base, as published. Nobody here has run it

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/image configurations
  • 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 every NEXT_PUBLIC_ for "is this really public?"
  • NXT-ENV-3 Verify by building and inspecting:
    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_SECRET only in server components, server actions, route handlers, or getServerSideProps / 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" in app/ 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-only package to fail-fast on accidental client imports of server modules:
    // 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-only similarly 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.
    '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 / tenantId as 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.ts and every API route in pages/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.matcher field).
  • NXT-MW-2 Middleware running on the Edge runtime can't use Node.js APIs; if you need crypto for 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.remotePatterns lists 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/image which 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-security skill.
  • NXT-AUTH-3 If using Clerk: see clerk-security skill.
  • 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. (see saas-security-pack/saas-frontend-hardening).
  • NXT-CFG-2 poweredByHeader: false (removes X-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_*_SECRET env 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

What ships with it: 1 file

10.7 KB alongside SKILL.md

references/

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.