Skip to content

Next.js Security Cheat Sheet / Next.js 安全速查表

Introduction / 介绍

For the underlying runtime and secret handling, see the Node.js Security Cheat Sheet and Secrets Management Cheat Sheet.

有关底层运行时和密钥处理,请参阅Node.js 安全速查表和密钥管理速查表。

Next.js applications have several server entry points and can render or cache data on both sides of the server/client boundary. The framework's authentication guidance recommends placing authorization close to the data source instead of relying on routing or user interface checks.

Next.js 应用程序具有多个服务器入口点,可以在服务器/客户端边界两侧渲染或缓存数据。框架的身份验证指南建议将授权放置在数据源附近,而不是依赖于路由或用户界面检查。

Apply these principles to the relevant framework surfaces:

将这些原则应用于相关框架表面:

  • Classify every server entry point and enforce controls appropriate to its audience and effects.
    中文:对每个服务器入口点进行分类,并实施适合其受众和影响力的控制。
  • Return only data that the browser is authorized to receive and the application needs.
    中文:仅返回浏览器有权接收且应用程序需要的数据。
  • Include the intended audience in every cache decision.
    中文:在每次缓存决策中包含预期受众。
  • Treat routing and image configuration as security-sensitive code.
    中文:将路由和图像配置视为安全敏感代码。
  • Test controls by calling entry points directly, without using the user interface.
    中文:直接调用入口点进行测试控制,而不使用用户界面。

This sheet covers both the App Router and Pages Router. General JavaScript, authentication, Cross-Site Scripting (XSS), Cross-Site Request Forgery (CSRF), and Server-Side Request Forgery (SSRF) guidance is linked rather than repeated.

本页涵盖了应用路由器(App Router)和页面路由器(Pages Router)。一般JavaScript、身份验证、跨站脚本(XSS)、跨站请求伪造(CSRF)和服务器端请求伪造(SSRF)的指导链接而非重复。

Classify and Protect Server Entry Points / 分类和保护服务器入口点

Next.js applications have multiple server entry points. A check in one does not protect another independently callable path. For protected operations, enforce authorization at a boundary that every applicable path traverses. The Next.js Data Security guide recommends a server-only Data Access Layer (DAL) that performs authorization and returns minimal Data Transfer Objects (DTOs). An equivalent service-layer policy enforcement point or database control can also provide the boundary when all protected paths necessarily traverse it.

Next.js应用程序有多个服务器入口点。对一个入口点的检查并不能保护另一个独立可调用的路径。对于受保护的操作,在所有适用路径必须穿越的边界处执行授权。Next.js数据安全指南(Next.js Data Security guide)建议使用仅服务器数据访问层(DAL),该层执行授权并返回最小数据传输对象(DTO)。等效的服务层策略执行点或数据库控制也可以在所有受保护路径必须穿越它时提供边界。

Entry point / 入口点 Secure use / 安全使用
Proxy (proxy.ts in Next.js 16+; deprecated middleware.ts remains available during migration)
代理(Next.js 16+中的 proxy.ts;迁移期间仍可用的已弃用 middleware.ts)
Use for optimistic redirects and request filtering. Do not make it the only authorization layer.
用于乐观重定向和请求过滤。不要将其作为唯一的授权层。
Server Action
服务器操作
Treat each reachable action as a client-callable POST entry point. Validate input, then apply authentication and resource authorization when the operation is protected.
将每个可到达的操作视为一个客户端可调用的 POST 入口点。验证输入后,在操作受保护时应用身份验证和资源授权。
Route Handler (route.ts) or Pages API Route (pages/api)
路由处理器 (route.ts) 或页面 API 路由 (pages/api)
Treat it as an HTTP endpoint with an explicit audience. Apply the controls appropriate to a public endpoint, authenticated API, service endpoint, or webhook.
将其视为一个具有明确受众的 HTTP 端点。应用适用于公共端点、认证 API、服务端点或 webhook 的适当控制。
Server Component, page, or data loader
服务器组件、页面或数据加载器
Authorize before reading protected data. Return a narrow DTO rather than a database record.
在读取受保护数据之前进行授权。返回一个窄 DTO 而不是数据库记录。
Layout or Client Component
布局或客户端组件
A layout can enforce render-time access, but it does not protect independently callable descendants. Client Component checks only control what the user interface shows.
布局可以强制执行渲染时的访问权限,但它不会独立保护可调用的后代。客户端组件仅检查用户界面显示的内容。

Do not rely on Proxy or middleware alone / 不要仅依赖代理或中间件

Proxy can redirect unauthenticated users early, but its matcher may omit a route and routing changes can silently move an operation outside its coverage. Next.js explicitly states that Proxy should not be the only line of defense. Authorize protected operations again at the handler or data source.

代理可以提前重定向未认证的用户,但它的matcher可能省略一个路由,并且路由更改可能会静默地将操作移出其覆盖范围。Next.js明确指出代理不应是唯一的防线。在处理程序或数据源处再次授权受保护的操作。

This is also a defense against framework defects. CVE-2025-29927 allowed affected self-hosted Next.js versions to bypass authorization implemented only in middleware. Patch the framework, but keep authorization behind the routing layer so one bypass cannot expose data.

这同时也是对框架缺陷的防御。CVE-2025-29927允许受影响的自托管Next.js版本绕过仅在中间件中实现的授权。修补框架,但保持授权在路由层之后,以便一次绕过不会暴露数据。

Secure Server Actions as endpoints / 作为端点的安全服务器操作

A Server Action referenced by the application can receive a client-originated POST independently of the page that renders its form. Rendering the form only on a protected page does not authenticate the action request. Next.js documents that page-level authentication does not extend to Server Actions.

由应用程序引用的服务器操作可以独立于渲染其表单的页面接收客户端发起的POST请求。仅在受保护页面上渲染表单并不能验证操作请求。Next.js 文档指出页面级认证不扩展到服务器操作。

Classify each action as public or protected, then apply the relevant controls:

将每个操作分类为公开或受保护,然后应用相关控制:

  • Validate all arguments as untrusted input.
    中文:验证所有参数作为不受信任的输入。
  • For a protected action, derive the current authentication context on the server rather than accepting identity claims in its arguments.
    中文:对于受保护的操作,在服务器上推导当前认证上下文,而不是接受其参数中的身份声明。
  • Check permission on the exact protected object being read or changed; treat a user or tenant identifier submitted by the client as a selector, not authorization proof.
    中文:检查正在读取或更改的确切受保护对象上的权限;将客户端提交的用户或租户标识符视为选择器,而不是授权证明。
  • Return only authorized result fields because Server Action return values are serialized to the client.
    中文:仅返回授权的结果字段,因为服务器操作返回值被序列化到客户端。
  • Apply rate limits or stronger re-authentication to expensive or high-impact operations.
    中文:对昂贵或影响大的操作应用速率限制或更强的重新认证。

Next.js compares the request Origin with the host for Server Actions. Keep serverActions.allowedOrigins narrow when a trusted proxy requires additional origins. On a self-hosted deployment, ensure that only trusted infrastructure can establish the canonical Host or X-Forwarded-Host value seen by the application. A historical Server Action SSRF advisory, fixed in Next.js 14.1.1, demonstrates why patching and trustworthy host handling both matter. This built-in Origin check does not replace authentication, authorization, or the general controls in the CSRF Prevention Cheat Sheet.

Protect Route Handlers and Pages API Routes separately

Protecting a page does not protect a Route Handler or API Route that serves related data. Next.js says to treat Route Handlers as public-facing API endpoints. Classify each handler's audience: an intentionally public endpoint may require input validation and abuse controls, a webhook may authenticate a signature, and a protected API requires the applicable authentication plus object-level or tenant-level authorization from the Authorization Cheat Sheet.

Do not infer that a handler is private because only a Server Component calls it. If no browser, service, webhook, or external client needs the HTTP API, call the DAL directly from the Server Component and remove the extra entry point.

Protect Draft Mode as a privileged state change

If the application uses Draft Mode, treat the handler that enables it as a protected entry point. Calling enable() on the value returned by await draftMode() sets the __prerender_bypass cookie; it does not authenticate the caller or validate a secret by itself. The Draft Mode guide recommends validating a shared secret and confirming that the requested content exists before enabling the mode.

  • Authenticate the CMS or other caller and use a high-entropy secret when a shared-secret integration is appropriate.
  • Validate any requested content identifier against the trusted content source before enabling Draft Mode.
  • Redirect to a server-established path returned by that source, not directly to an untrusted query parameter.
    中文:重定向到由该源返回的服务器端设置的路径,而不是直接到不受信任的查询参数。
  • Test that an unauthenticated caller cannot obtain the __prerender_bypass cookie or use a Draft Mode entry point to expose unpublished content.
    中文:测试未经身份验证的调用者无法获取 __prerender_bypass 饼干或使用草稿模式入口来暴露未发布的内容。

Control Data Crossing into the Browser / 控制数据跨入浏览器

Code running only on the server can still send its return values to the browser. The App Router serializes values passed to Client Components, and the Pages Router exposes page props in the initial HTML. The Pages Router documentation warns that getServerSideProps values are visible to the client.

仅在服务器上运行的代码仍然可以向浏览器发送其返回值。App Router 序列化传递给客户端组件的值,而 Pages Router 在初始 HTML 中暴露页面属性。Pages Router 文档警告称 getServerSideProps 的值对客户端可见。

  • Construct an explicit DTO containing only fields the browser is authorized to receive. Selecting only required columns at the data source provides additional defense in depth.
    中文:构建一个显式的 DTO,其中只包含浏览器有权接收的字段。在数据源中选择仅需要的列提供额外的深度防御。
  • Do not pass ORM records, session objects, or configuration merely because they are available. Do not send secrets to Client Components. Any token intentionally sent to the browser must be narrowly scoped and treated as exposed; configuration must be explicitly classified as public.
    中文:不要仅仅因为它们可用就传递 ORM 记录、会话对象或配置。不要将机密发送到客户端组件。任何有意发送到浏览器的令牌都必须具有狭窄的作用域,并被视为暴露;配置必须明确分类为公开。
  • Keep Server Action return values authorized and minimal; a server-side function does not make its returned value secret.
    中文:保持服务器操作返回值授权和最小化;服务器端函数不会使其返回值保密。
  • Treat values returned in the props from getStaticProps, getServerSideProps, and getInitialProps as visible to that page's browser.
    中文:将 getStaticProps、getServerSideProps 和 getInitialProps 返回的 props 中的值视为该页面浏览器的可见内容。
  • Prefix an environment variable with NEXT_PUBLIC_ only when its value is intentionally public. The value is included in client JavaScript according to the Next.js environment variable guide.
    中文:仅当环境变量的值有意公开时,才以 NEXT_PUBLIC_ 为前缀。根据 Next.js 环境变量指南,该值将包含在客户端 JavaScript 中。

Importing server-only in a sensitive module is a useful build-time guard because it prevents that module from being imported into a Client Component. It does not stop server code from explicitly returning sensitive data. React taint APIs can add another guard, but Next.js describes tainting as defense in depth, not a replacement for shaping data.

在敏感模块中导入 server-only 是一个有用的构建时保护措施,因为它阻止该模块被导入到客户端组件中。它不会阻止服务器代码明确返回敏感数据。React 污染 API 可以添加另一个保护措施,但 Next.js 将 污染描述为深度防御,而不是替代数据整形。

For browser rendering sinks and React-specific client concerns, use the XSS Prevention Cheat Sheet and DOM-based XSS Prevention Cheat Sheet.

针对浏览器渲染接收器和React特定的客户端问题,请使用XSS 防范技巧表和基于DOM的XSS防范技巧表。

Scope Caches to Their Audiences / 将缓存范围限制在其受众

Before caching a response or function result, classify its audience, such as public, tenant-scoped, user-scoped, permission-set, locale, cohort, or request-specific. A cache entry must not be reusable by a broader audience than the data permits. With use cache, Next.js includes serializable arguments and captured closure values in the generated cache key. Include a verified user, tenant, or other audience dimension when it changes the cached value or a cached authorization decision. When content is identical across authorized callers and authorization is enforced separately before return, do not duplicate the cache merely by identity.

在缓存响应或函数结果之前,将其受众分类,例如公共、租户范围、用户范围、权限集、地区、群体或请求特定。缓存条目不应被比数据允许的更广泛的受众重复使用。使用use cache时,Next.js包括可序列化的参数和捕获的闭包值在生成的缓存键中。当更改缓存的值或缓存的授权决策时,包括已验证的用户、租户或其他受众维度。当内容在授权调用者之间相同且在返回之前单独执行授权时,不要仅通过身份重复缓存内容。

  • Establish and verify the required authorization context before returning protected cached data. Depending on the design, this may be a user identity, service identity, or validated capability.
    中文:在返回受保护的缓存数据之前建立和验证所需的授权上下文。根据设计,这可能是一个用户身份、服务身份或验证的能力。
  • Include only verified dimensions that change the cached value or cached authorization decision, such as user ID, tenant ID, permission version, or locale. Do not use a raw cookie or bearer token as a cache key.
    中文:仅包括更改缓存值或缓存授权决策的已验证维度,例如用户ID、租户ID、权限版本或地区。不要使用原始cookie或bearer token作为缓存键。
  • Do not put user-specific data in a use cache function that has no user-specific input.
    中文:不要将用户特定数据放入没有用户特定输入的use cache函数中。
  • Use caches that can serve a response before per-request application authorization, such as Incremental Static Regeneration (ISR), getStaticProps, or shared CDN caching, only for data the full cache audience may read. Next.js states that getStaticProps data must be publicly cacheable.
    中文:仅对全缓存受众可能读取的数据使用可以在请求应用授权之前提供响应的缓存,例如增量静态再生 (ISR)、getStaticProps 或共享 CDN 缓存。Next.js 指出,getStaticProps 数据必须是公开可缓存的。
  • A server-side data or fetch cache may hold protected content shared by authorized callers when every return path authorizes access and the key separates every content variant.
    中文:当每个返回路径都授权访问且键区分每个内容变体时,服务器端数据或fetch缓存可以持有由授权调用者共享的受保护内容。
  • Do not add shared Cache-Control directives to personalized getServerSideProps responses.
    中文:不要向个性化的getServerSideProps响应中添加共享的Cache-Control指令。
  • After authorization or tenancy changes, prevent reuse under stale permissions by invalidating affected keys or tags, advancing a permission version in the key, or using another bounded expiration strategy.

Treat cache invalidation as a mutation capability. revalidatePath and revalidateTag can be called from server entry points, while updateTag is limited to Server Actions. Authenticate and authorize callers, derive the invalidation target from an authorized object or validate it against constrained application-owned path and tag patterns, and apply abuse controls to externally reachable invalidation handlers. A deliberately global purge should require the correspondingly privileged operation.

use cache: private can read request-time values, but its results are cached in the browser's memory and are still delivered to that browser. The directive documentation does not make over-broad data safe to return.

For user-, tenant-, or permission-scoped caches, test representative identities with different entitlements: fill the cache as identity A, then request the same route and object identifiers as identity B. Repeat after changing a role or tenant membership. This catches missing audience keys that a positive-path cache test cannot.

Treat Next.js Configuration as Security Code

Review next.config.*, Proxy matchers, and route configuration with the same care as application handlers. Next.js rewrites act as a URL proxy, and matcher values can flow into destinations.

  • Resolve external rewrite hosts from a fixed allowlist or a server-controlled registry. Do not let an untrusted header, host, cookie, or query capture select an upstream scheme, authority, or port.
  • For a protected destination, ensure direct requests cannot bypass equivalent authentication and authorization. Enforcement may live at the destination or at a trusted gateway whose network policy blocks direct access. A rewrite masks the destination URL; it does not create an authorization boundary.
  • Do not let untrusted captures select the scheme or authority of an external redirect. Validate any interpolated path or query component using the Unvalidated Redirects and Forwards Cheat Sheet.
    中文:不要让不受信任的捕获选择外部重定向的方案或权限。使用未经验证的重定向和转发备忘单验证任何插值路径或查询组件。
  • Define every images.remotePatterns restriction the application can enforce. Next.js warns that omitted fields imply broad wildcards; allow port, pathname, or query variation only when the use case requires it and the trust model accounts for the broader match.
    中文:定义应用程序可以实施的每个 images.remotePatterns 限制。Next.js 警告称,省略的字段意味着广泛的通配符;只有在用例需要且信任模型考虑了更广泛的匹配时,才允许端口、路径名或查询的变化。
  • Keep images.dangerouslyAllowLocalIP disabled unless a reviewed private-network use case requires it. Next.js warns that enabling it can let users access content on the internal network. Apply the SSRF Prevention Cheat Sheet to any server-side fetch destination.
    中文:除非经过审查的私有网络用例需要,否则请保持 images.dangerouslyAllowLocalIP 禁用。Next.js 警告称,启用它可能会让用户 访问内部网络上的内容。将 SSRF 防范备忘单应用于任何服务器端获取目标。
  • Keep serverActions.allowedOrigins restricted to trusted application and proxy origins.
    中文:将serverActions.allowedOrigins限制在受信任的应用和代理源上。
  • Leave productionBrowserSourceMaps disabled unless the operational need justifies publicly serving the original browser source maps. Enabling it causes Next.js to emit and automatically serve those files.
    中文:除非运营需求证明公开提供原始浏览器源映射文件是合理的,否则请禁用 productionBrowserSourceMaps。启用它会导致 Next.js 自动发出并服务这些文件。
  • Deploy an optimized production build with an appropriate production server or adapter. Do not expose next dev, which enables development-mode hot reloading and error reporting, as the production service.
    中文:使用适当的生成服务器或适配器部署优化的生产构建。不要将 next dev(它启用了开发模式的热重载和错误报告)作为生产服务暴露。

Security-sensitive configuration assembled from environment variables is still code. Validate hosts and origins against an allowlist at startup and fail closed when a required value is missing or invalid. Validate other configuration using an appropriate schema, type, or range constraint.

从环境变量组装的安全敏感配置仍然是代码。在启动时验证主机和源与允许列表,当缺少或无效的必需值时关闭失败。使用适当的模式、类型或范围约束验证其他配置。

Choose a CSP compatible with the rendering model / 选择与渲染模型兼容的CSP

Use a Content Security Policy (CSP) appropriate to the application's script, style, and third-party resource requirements; see the Content Security Policy Cheat Sheet for general policy design. Next.js can generate a fresh nonce in Proxy and apply it during rendering. A nonce must be unpredictable and unique for each response; do not cache HTML in a way that reuses it for another response.

使用适合应用程序脚本、样式和第三方资源需求的Content Security Policy (CSP);参见内容安全策略备忘单以获取一般策略设计。Next.js可以在代理中生成新的nonce并在渲染时应用它。nonce必须对每个响应都是不可预测且唯一的;不要以重复使用HTML的方式缓存HTML,使其为另一个响应服务。

Nonce-based CSP has an architectural cost: Next.js requires dynamic rendering, disables static optimization and ISR for those pages, and does not support Partial Prerendering (PPR) with request-specific nonces. Applications that retain static rendering can use a CSP without nonces when their resource policy permits it. Do not weaken a production policy with development-only directives such as 'unsafe-eval' merely to make the development server work.

基于nonce的CSP有架构成本:Next.js需要动态渲染,禁用静态优化和ISR对这些页面,并且不支持带有请求特定nonce的局部预渲染(PPR)。保留静态渲染的应用程序可以在其资源策略允许的情况下使用不带nonce的CSP。不要为了使开发服务器工作而仅使用开发专用指令(如'unsafe-eval')来削弱生产策略。

Verify the Boundaries / 验证边界

Framework controls need direct negative-path tests. The Next.js production checklist recommends checking authorization inside protected Server Actions rather than relying on Proxy, layouts, or pages.

框架控制需要直接的负路径测试。Next.js生产清单建议在受保护的Server Actions内部检查授权,而不是依赖于代理、布局或页面。

  • Inventory application-defined Server Actions, Route Handlers, Pages API Routes, Draft Mode entry points, server-side data loaders, Proxy matchers, cached functions, cache-invalidation call sites, rewrites, redirects, CSP configuration, source map settings, and remote image patterns. Classify each applicable audience and effect.
    中文:定义服务器操作、路由处理程序、页面API路由、草稿模式入口点、服务器端数据加载器、代理匹配器、缓存函数、缓存失效调用点、重写、重定向、CSP配置、源映射设置和远程图像模式。对每个适用受众和影响进行分类。
  • Call actions and handlers directly without first loading their page. For protected operations, verify the applicable unauthenticated, unauthorized, wrong-owner, and wrong-tenant requests fail. For public operations, verify the intended public behavior and abuse controls.
    中文:直接调用操作和处理器,而无需首先加载它们的页面。对于受保护的操作,验证适用的未认证、未授权、错误所有者或错误租户请求失败。对于公共操作,验证预期的公共行为和滥用控制。
  • For protected route families that use Proxy for early filtering, exercise an unmatched or bypassed-Proxy path and prove the handler or data boundary still denies unauthorized access.
    中文:对于使用代理进行早期过滤的受保护路由族,执行未匹配或绕过代理的路径,并证明处理器或数据边界仍然拒绝未授权访问。
  • Inspect the applicable rendered HTML, React Server Component payloads, Pages Router data responses, and Server Action responses for fields that should remain server-only.
    中文:检查适用的渲染HTML、React服务器组件有效负载、页面路由数据响应和服务器操作响应中应保持服务器端字段。
  • Run cross-user and cross-tenant tests for audience-scoped caches, including after permission changes and revalidation.
    中文:运行跨用户和跨租户测试,包括在权限更改和重新验证后,针对受众范围缓存。
  • Call Draft Mode and cache-invalidation handlers directly and prove that unauthorized callers cannot enable preview state or invalidate content.
    中文:直接调用草稿模式和缓存失效处理器,并证明未授权调用者无法启用预览状态或使内容失效。
  • Keep Next.js on a supported patched release. CVE-2024-46982 is an example where an affected Pages Router response could be cached when the application intended otherwise.
    中文:保持 Next.js 在受支持的修补版本上。CVE-2024-46982 是一个例子,其中受影响的 Pages Router 响应可能会在应用程序本意之外被缓存。

Security tests should fail when a new application entry point or cache is added without an explicit classification. A fixed hand-maintained list can miss the new file for the same reason the control was omitted, so derive the inventory from the route and source tree where practical.

当添加新的应用程序入口点或缓存而没有明确的分类时,安全测试应该失败。固定的手动维护列表可能会因为与控制被省略相同的原因而错过新文件,因此尽可能从路由和源树中推导出清单。

References / 参考