{"slug":"nextjs-server-security-review","title":"nextjs-server-security-review","summary":"Statically review Next.js middleware, Server Actions, next.config.js, and environment-variable files for four documented server-side defect classes -- middleware matcher exclusions that silently skip auth on Server Functions, Server Actions missing allowedOrigins CSRF protection,","platform":"Claude","tags":[],"authorName":"LLM Mart","authorSlug":"llm-mart","score":0,"source":"github","price":null,"verified":false,"createdAt":"2026-10-05T21:52:15.645839Z","repo":{"url":"https://github.com/VincentChuWaiChow/vanguard-frontier-agentic","stars":24,"forks":3,"license":"Apache-2.0","updatedAt":"2026-10-05T13:00:24Z"},"bodyHtml":"<hr>\n<h2>name: nextjs-server-security-review\ndescription: Statically review Next.js middleware, Server Actions, next.config.js, and environment-variable files for four documented server-side defect classes -- middleware matcher exclusions that silently skip auth on Server Functions, Server Actions missing allowedOrigins CSRF protection, secrets leaked via NEXT_PUBLIC_ prefixes, and SSRF/open-redirect via dangerouslyAllowLocalIP or unvalidated rewrite destinations.\nallowed-tools: Read Grep Glob\nmetadata:\nauthor: \"github: VincentChuWaiChow\"\nversion: \"0.1.0\"\nupdated: \"2026-07-03\"\ncategory: security</h2>\n<h1>Next.js Server Security Review</h1>\n<h2>Purpose</h2>\n<p>Review Next.js middleware (<code>middleware.ts</code>/<code>.js</code>), Server Actions, <code>next.config.js</code>, and environment-variable files for the concrete server-side defect classes Next.js's own documentation calls out directly: middleware <code>matcher</code> exclusions that silently skip authorization for Server Functions, Server Actions missing <code>allowedOrigins</code> CSRF protection, secrets accidentally exposed to the client via a <code>NEXT_PUBLIC_</code> prefix, and server-side request forgery / open-redirect risk via <code>dangerouslyAllowLocalIP</code> or an unvalidated rewrite destination. This skill exists so the review stays anchored to these documented defect classes instead of drifting into a general \"Next.js code review\" of component architecture, data fetching patterns, or styling.</p>\n<h2>When to use</h2>\n<p>Use this skill when the user asks to:</p>\n<ul>\n<li>review <code>middleware.ts</code>/<code>middleware.js</code> and its <code>matcher</code> configuration for authorization gaps,</li>\n<li>assess whether a Server Action is protected against CSRF, or whether <code>next.config.js</code>'s <code>serverActions.allowedOrigins</code> is configured correctly for a reverse-proxy or multi-zone deployment,</li>\n<li>audit <code>.env</code>/<code>.env.production</code> files or any <code>process.env.NEXT_PUBLIC_*</code> usage for accidental secret exposure to the client bundle,</li>\n<li>review <code>next.config.js</code> image configuration (<code>images.dangerouslyAllowLocalIP</code>) or <code>rewrites()</code>/<code>NextResponse.rewrite()</code> usage for SSRF or open-redirect risk,</li>\n<li>perform a pre-launch security review of a Next.js server surface (middleware, Server Actions, config, env files).</li>\n</ul>\n<p>Do not use this skill for:</p>\n<ul>\n<li>client-only React component logic with no middleware, Server Action, config, or environment-variable surface in scope — there is no server-side sink for this skill to review,</li>\n<li>general Next.js performance, data-fetching-pattern, or App Router/Pages Router migration review with no security angle,</li>\n<li>a bug that requires live traffic reproduction (actually triggering a CSRF request cross-origin, actually confirming an SSRF callback from a deployed image optimizer) to prove exploitation — static analysis proves the structural risk, not that it has already been exploited in production.</li>\n</ul>\n<h2>Context7 Documentation Protocol</h2>\n<ul>\n<li>Resolve the Next.js library ID with <code>resolve-library-id</code> (matched result: <code>/vercel/next.js</code>) before citing any middleware, Server Actions, environment-variable, or <code>next.config.js</code> behavior claim.</li>\n<li><code>/vercel/next.js</code> is a high-reputation source covering authentication, middleware, Server Actions, environment variables, and <code>next.config.js</code> security patterns directly from the framework's own docs and source. Use <code>query-docs</code> against it to confirm exact option names (<code>serverActions.allowedOrigins</code>, <code>images.dangerouslyAllowLocalIP</code>) and documented behavior (<code>NEXT_PUBLIC_</code> inlining, matcher exclusion semantics) before writing a finding.</li>\n<li>Read <code>package.json</code> first to confirm the Next.js major version and whether the app uses the App Router or Pages Router — <code>experimental.serverActions</code> configuration, middleware <code>matcher</code> conventions, and <code>NextResponse.rewrite()</code> APIs have shifted across major versions; do not apply App Router API names to a Pages Router codebase or vice versa.</li>\n<li>If Context7 is unavailable, fall back to the <code>official_docs</code> URLs in this skill's <code>metadata.json</code> and label the claim <code>documentation-based, unverified against current release</code>.</li>\n</ul>\n<h2>Lean operating rules</h2>\n<ul>\n<li>All four defect classes in this skill's scope default to HIGH severity. This is a security-scoped skill: do not downgrade a middleware-matcher authorization gap, a missing CSRF allowlist, a leaked secret, or a structural SSRF/open-redirect path to MEDIUM just because it has not been observed exploited yet — the risk is in the structure, not in whether someone has already hit it.</li>\n<li>Trace every finding to a concrete file:line and a concrete data-flow path. A finding that says \"this middleware might not protect everything\" or \"this env var might leak\" without showing the specific <code>matcher</code> pattern, the specific <code>serverActions</code> config, or the specific variable declaration is not a valid finding — it is a guess.</li>\n<li>Never accept a middleware <code>matcher</code> as sufficient authorization coverage in isolation. A <code>matcher</code> whose negative-lookahead pattern excludes a path (e.g. <code>/((?!api|_next).*)</code>) means middleware — and any auth check it performs — never runs for that excluded path; a Proxy matcher that excludes a path also skips Server Function calls on that path. Confirm the excluded path's own handlers (Server Actions, Route Handlers) independently verify the session themselves.</li>\n<li>Never approve a <code>next.config.js</code> with a <code>serverActions</code> block configured for a reverse-proxy, multi-zone, or otherwise cross-origin deployment unless <code>allowedOrigins</code> is explicitly present in that same block. Next.js's default CSRF protection compares the Server Action request's <code>Origin</code> header to the <code>Host</code> header and rejects mismatches — a deployment where those two headers legitimately differ (reverse proxy, multi-zone) needs the allowlist or every legitimate request fails, or worse, the mismatch is worked around insecurely elsewhere.</li>\n<li>Flag every environment variable whose name suggests a secret (contains <code>KEY</code>, <code>SECRET</code>, <code>TOKEN</code>, <code>PASSWORD</code>, <code>CREDENTIAL</code>, or equivalent) and is prefixed <code>NEXT_PUBLIC_</code>. Any <code>NEXT_PUBLIC_</code> variable is inlined into the JavaScript bundle at build time and shipped to every client, full stop — there is no runtime gate that can retroactively hide it once bundled. The safe fix is to drop the prefix and read the value only from server-side code via <code>process.env.API_KEY</code> (or the equivalent unprefixed name), never from a Client Component.</li>\n<li>Flag <code>images.dangerouslyAllowLocalIP: true</code> in <code>next.config.js</code> as a structural SSRF risk unless the codebase demonstrably validates every dynamic <code>src</code> value against a hardcoded external-hostname allowlist before it reaches the <code>&lt;Image&gt;</code> component.</li>\n<li>Flag any <code>NextResponse.rewrite()</code> call (or <code>rewrites()</code> destination) whose target URL is built directly from user-controlled input (query parameters, headers, request body) with no hostname allowlist check on the resolved value before the rewrite call — this is SSRF/open-redirect via the rewrite backend, not a cosmetic routing bug.</li>\n<li>Never execute, build, or run application code, and never send live requests, as part of this review; this is a static-review skill (Read/Grep/Glob only).</li>\n<li>Load only the reference needed for the concern in scope.</li>\n</ul>\n<h2>References</h2>\n<p>Load these only when needed:</p>\n<ul>\n<li><a href=\"references/workflow-and-output.md\">Review workflow and findings contract</a> — use for the step-by-step review procedure, the decision tree per defect class, and the required output shape.</li>\n<li><a href=\"references/middleware-and-server-actions.md\">Middleware and Server Actions boundary defects</a> — load only when reviewing <code>middleware.ts</code>/<code>.js</code>, its <code>matcher</code>, or Server Action CSRF configuration.</li>\n<li><a href=\"references/env-and-ssrf-surfaces.md\">Environment variables and SSRF/redirect surfaces</a> — load only when the review scope includes <code>.env*</code> files, <code>NEXT_PUBLIC_*</code> usage, <code>images.dangerouslyAllowLocalIP</code>, or a rewrite/redirect destination built from dynamic input. Includes the OWASP SSRF/open-redirect grounding reference; load that citation only when such a finding is actually present.</li>\n</ul>\n<h2>Response minimum</h2>\n<p>Return, at minimum:</p>\n<ul>\n<li>the middleware file(s), Server Action(s), <code>next.config.js</code>, and/or environment file(s) in scope,</li>\n<li>ranked findings with file:line evidence, defect category (<code>middleware-auth-gap</code>, <code>csrf-origin</code>, <code>secret-leak</code>, or <code>ssrf-redirect</code>), the concrete data-flow trace (the <code>matcher</code> pattern and the excluded path's own auth handling, the <code>serverActions</code> config and its deployment topology, the environment variable declaration and its usage site, or the origin-to-sink path for the SSRF/redirect finding), and a fix sketch matching Next.js's documented pattern,</li>\n<li>for every middleware-auth-gap finding, an explicit statement of whether the excluded path's own handler independently verifies the session — never approve on the assumption it does,</li>\n<li>evidence level per finding (<code>repo evidence</code>, <code>documentation-based</code>, or <code>inference</code>), with structural risk findings explicitly labeled as structural risk, not as confirmed-exploited,</li>\n<li>verdict (approve / approve-with-notes / block),</li>\n<li>open questions or scope the review could not cover (e.g., \"confirming actual cross-origin CSRF success requires a live cross-origin request, not static review\").</li>\n</ul>\n","files":[{"path":"metadata.json","sizeBytes":2037,"isText":true},{"path":"references/env-and-ssrf-surfaces.md","sizeBytes":6928,"isText":true},{"path":"references/middleware-and-server-actions.md","sizeBytes":5488,"isText":true},{"path":"references/workflow-and-output.md","sizeBytes":6786,"isText":true},{"path":"SKILL.md","sizeBytes":9113,"isText":true}],"reviewScore":null,"reviewSummary":null,"trust":{"provenance":"trusted-source-unreviewed","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow.","bodySource":null},"bodyLocked":false,"purchaseUrl":null,"sourceUrl":null,"report":{"provenance":"trusted-source-unreviewed","screen":{"ran":true,"outcome":"notes-only","suspicious":0,"notes":13,"hiddenCharacters":false},"virusScan":{"engine":"clamav","status":"clean","scannedAt":"2026-10-05T21:58:45.117464Z","sha256":"E60D6BAACADFCBC2AEB85D6805D80E0CF3D37240ED7DBD802F9CF878A5DAF023","sizeBytes":13205},"review":null,"source":{"repositoryUrl":"https://github.com/VincentChuWaiChow/vanguard-frontier-agentic","path":"skills/frontend/nextjs-server-security-review","license":"Apache-2.0","commit":"febe32a08e78fd06b1e466187410d673f1958d87","subtreeSha":"9EAB6BFB6D911CA6E3407453E25E2E2C071620E4E15B95209CADFA332DD46DE0","lastSyncedAt":"2026-10-05T21:51:58.639905Z"},"reviewedAt":"2026-10-05T22:12:17.563735Z","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow."},"install":[{"target":"skills-cli","command":"npx skills add https://github.com/VincentChuWaiChow/vanguard-frontier-agentic/tree/master/skills/frontend/nextjs-server-security-review"},{"target":"claude-code","command":"claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install vincentchuwaichow-vanguard-frontier-agentic@llmmart"},{"target":"git","command":"git clone https://github.com/VincentChuWaiChow/vanguard-frontier-agentic.git"}]}