跳转到正文
报告库
用途分类 / 数据分析

Nextjs App Router Patterns Skill 安全审计

作者说它能做什么(原文)

Master Next.js 14+ App Router with Server Components, streaming, parallel routes, and advanced data fetching. Use when building Next.js applications, implementing SSR/SSG, or optimizing React Server Components.

第三方安全检查结论

先别安装或运行

已检查文件
2
发现的风险
3
会不会运行危险命令?检查是否下载程序后直接运行、让他人远程控制电脑,或藏起要运行的命令。未发现风险
会不会泄露文件和密钥?检查是否发送含密码或密钥的文件,以及代码里是否直接写了密钥。未发现风险
会不会删除文件或一直在后台运行?检查是否大范围删除文件、改写磁盘,或设置自动启动。未发现风险
会不会绕过安全保护?检查是否跳过网站安全验证、开放过多文件权限,或取消操作前的确认。发现 2 项风险
高风险

产品 API 示例允许未经身份或权限检查的数据库创建,并直接接受整个请求体

原文依据:1 处
发现了什么

POST 处理器解析调用者提供的 JSON 后,将其完整传给 db.product.create。示例中没有身份验证、角色检查、字段白名单或结构验证。

为什么需要注意

如果该模式被直接用于可访问的路由,任何能够调用端点的人都可能创建产品,或通过额外字段修改价格、所有者、发布状态等本应受控的属性。

这是文档中的示例而非正在运行的代码,但该技能明确提供可用于构建全栈功能的模式。若用户照搬此 POST 处理器,任何能访问端点的调用者都可把任意 JSON 直接交给数据库创建产品;示例未显示身份认证、创建权限、字段白名单或结构验证,可能导致未授权记录或敏感字段被写入。用户可要求作者补充认证、角色授权和严格输入模式,或限制该示例不得直接用于生产环境。

references/details.md:327来自说明文档打开原文件
export async function POST(request: NextRequest) {  const body = await request.json();  const product = await db.product.create({    data: body,  });  return NextResponse.json(product, { status: 201 });}
高风险

产品更新 Server Action 示例可按调用者提供的 ID 和数据直接修改数据库

原文依据:1 处
发现了什么

updateProduct 直接将 id 和 data 交给数据库更新,没有展示用户身份、对象所有权、管理员权限或字段限制。标记为 “use server” 并不会自动提供业务授权。

为什么需要注意

若该导出 Action 可由客户端触发,未获授权的用户可能修改任意产品及敏感属性,并立即使缓存失效、将更改传播到页面。

这是缓存失效章节中的示例,不是已部署实现;不过若按示例用于 Server Action,调用者提供的 id 和整个 data 会直接进入数据库更新。代码未显示身份认证、对象所有权或管理员权限检查,也未限制可修改字段;“use server”只决定执行位置,不提供业务授权。结果可能是越权修改其他产品或敏感字段。用户可要求作者加入授权和字段白名单,并限制哪些客户端能调用该操作。

references/details.md:419来自说明文档打开原文件
// Invalidate via Server Action("use server");import { revalidateTag, revalidatePath } from "next/cache";export async function updateProduct(id: string, data: ProductData) {  await db.product.update({ where: { id }, data });  revalidateTag("products");  revalidatePath("/products");}
会不会误导 AI 或隐藏内容?检查工作说明是否要求 AI 忽略你的指令、干扰检查结果,或夹带看不见的文字。未发现风险
会不会偷偷改推广链接或收款方?检查是否强制替换推广链接或收款对象,同时要求隐瞒更改。发现 1 项风险
高风险

结账示例仅检查地址和 payment 是否非空就处理订单

原文依据:1 处
发现了什么

checkout 接受表单中的 address 和 payment 字符串,只做非空检查,随后调用 processOrder;示例没有展示会话、购物车所有权、金额重算、支付令牌验证或最终确认。

为什么需要注意

直接采用时,伪造或无效字段可能触发错误订单、错误收费或绕过服务端定价检查;若 payment 包含原始支付资料,还会扩大敏感支付数据的处理范围。

这是简化的结账模式示例,实际支付细节可能被抽象在 processOrder 内,因此不能断言其必然不安全。但可见代码只从表单读取两个字符串并检查非空,未展示用户会话、购物车归属、服务端金额重算或支付令牌验证。若 processOrder 没有独立执行这些检查,照搬后可能造成越权结账、金额或支付数据被篡改。用户可要求作者明确这些检查必须在可信的服务端流程中完成,且不要接受原始支付凭据。

references/details.md:139来自说明文档打开原文件
export async function checkout(formData: FormData) {  const address = formData.get("address") as string;  const payment = formData.get("payment") as string;  // Validate  if (!address || !payment) {    return { error: "Missing required fields" };  }  // Process order  const order = await processOrder({ address, payment });  // Redirect to confirmation  redirect(`/orders/${order.id}/confirmation`);}

Skill 逻辑拆解

5 个说明模块

该 Skill 是面向 Next.js App Router 开发的指导资料,并明确要求在简要说明不足时读取详细示例文件;所提供内容是文档和代码片段,不是自动安装或执行脚本。

查看原文
SKILL.md:3来自说明文档打开原文件
name: nextjs-app-router-patternsdescription: Master Next.js 14+ App Router with Server Components, streaming, parallel routes, and advanced data fetching. Use when building Next.js applications, implementing SSR/SSG, or optimizing React Server Components.---
SKILL.md:96来自说明文档打开原文件
Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.

示例展示了服务器端数据库写入、订单处理和缓存失效。这些片段只有在用户或代理将其复制到应用并部署后才会产生实际影响。

查看原文
references/details.md:126来自说明文档打开原文件
  try {    await db.cart.upsert({      where: { sessionId_productId: { sessionId, productId } },      update: { quantity: { increment: 1 } },      create: { sessionId, productId, quantity: 1 },    });    revalidateTag("cart");    return { success: true };
references/details.md:148来自说明文档打开原文件
  // Process order  const order = await processOrder({ address, payment });  // Redirect to confirmation  redirect(`/orders/${order.id}/confirmation`);}
references/details.md:423来自说明文档打开原文件
export async function updateProduct(id: string, data: ProductData) {  await db.product.update({ where: { id }, data });  revalidateTag("products");  revalidatePath("/products");}

数据获取示例会向配置的 API 主机发送来自页面筛选条件的查询参数;主机由 API_URL 环境变量决定。

查看原文
references/details.md:44来自说明文档打开原文件
// components/products/ProductList.tsx - Server Componentasync function getProducts(filters: ProductFilters) {  const res = await fetch(    `${process.env.API_URL}/products?${new URLSearchParams(filters)}`,    { next: { tags: ['products'] } }  )  if (!res.ok) throw new Error('Failed to fetch products')  return res.json()}
从这里开始 · 工作说明SKILL.md
nextjs-app-router-patterns
连线表示工作说明包含的模块,不是实际运行顺序。点击模块可查看原文。

文件引用关系图

1 处引用
哪些文件发起引用引用了什么
连线表示真实的文件引用,不是运行顺序。点击节点可高亮相关连线,并查看具体文件和原文位置。虚线表示还有文件需要定位。
文件与检查记录2 个文件

检查范围与遗漏

逐文件查看涉及的内容

下方列出本次涉及的原文范围;纳入检查不代表已查清所有问题。

  • SKILL.md已纳入全文
  • references/details.md已纳入全文

这份报告只针对上方版本。我们看了拿到的代码和说明文件,没有实际运行 Skill,也没有检查它另外安装的软件包。因此,这不是“保证安全”的承诺;换了版本或使用环境,结果也可能不同。

  • SKILL.md工作说明
  • references/details.md配套文件

代码和说明中提到的操作

连接外部网站
SKILL.md:76来自说明文档打开原文件
async function getProducts() {  const res = await fetch('https://api.example.com/products', {    next: { revalidate: 3600 }, // ISR: revalidate every hour
references/details.md:45来自说明文档打开原文件
async function getProducts(filters: ProductFilters) {  const res = await fetch(    `${process.env.API_URL}/products?${new URLSearchParams(filters)}`,
references/details.md:408来自说明文档打开原文件
// No cache (always fresh)fetch(url, { cache: "no-store" });
读取文件
SKILL.md:96来自说明文档打开原文件
Detailed pattern documentation lives in `references/details.md`. Read that file when the navigation tier above is insufficient.
读取密钥或账号配置
references/details.md:46来自说明文档打开原文件
  const res = await fetch(    `${process.env.API_URL}/products?${new URLSearchParams(filters)}`,    { next: { tags: ['products'] } }
读取了多少行
544
文件校验值(用于核对版本)
c6e020c9f1307f8239cf5f9182d6eb111a2dc13c4a9fb4870d2937efb552ee4c