SuperAPI AI 工具集

security-nextjs

安全与审计

查看项目

更新于 10-15 15:44

技能介绍

用途

该技能面向 Next.js 应用的安全审计,提供一套可复用的检查模式,覆盖 App Router、Server Actions、API 路由与 middleware 等常见攻击面。适用于代码审查、上线前安全自查以及排查环境变量泄露等场景。

主要能力

环境变量泄露审计

核心判断规则:

  • NEXT_PUBLIC_* → 会被打包进客户端 JavaScript → 所有人可见
  • 无前缀 → 仅服务端可用 → 可安全存放密钥

审计步骤:

grep -r "NEXT_PUBLIC_" . -g "*.env*"

对每个变量提问:“如果它出现在 view-source 里,我能接受吗?”

常见错误示例:

  • NEXT_PUBLIC_API_KEY(应为服务端专用)
  • NEXT_PUBLIC_DATABASE_URL(绝对不可使用)
  • NEXT_PUBLIC_STRIPE_SECRET_KEY(应改用 STRIPE_SECRET_KEY)

安全模式示例:

// 仅服务端(API 路由、Server Component、Server Action)
const apiKey = process.env.API_KEY; // ✓ 无 NEXT_PUBLIC_ 前缀

// 客户端安全(真正公开的值)
const publishableKey = process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY; // ✓ 可公开

next.config.js 中的 env 字段始终会被打包:即使没有 NEXT_PUBLIC_ 前缀,写在 env 下的值也会被内联进客户端 bundle,应视为公开。

// ❌ 此处的敏感值会暴露给浏览器
module.exports = {
  env: {
    DATABASE_URL: process.env.DATABASE_URL,
  },
};

Server Actions 安全

最常见的缺失是鉴权:

// ❌ 存在漏洞:无鉴权检查
"use server"
export async function deleteUser(userId: string) {
  await db.user.delete({ where: { id: userId } });
}

// ✓ 安全:鉴权 + 授权
"use server"
export async function deleteUser(userId: string) {
  const session = await getServerSession();
  if (!session) throw new Error("Unauthorized");
  if (session.user.id !== userId && !session.user.isAdmin) {
    throw new Error("Forbidden");
  }
  await db.user.delete({ where: { id: userId } });
}

输入校验:

// ❌ 信任客户端输入
"use server"
export async function updateProfile(data: any) {
  await db.user.update({ data });
}

// ✓ 使用 Zod 校验
"use server"
import { z } from "zod";
const schema = z.object({ name: z.string().max(100), bio: z.string().max(500) });
export async function updateProfile(formData: FormData) {
  const data = schema.parse(Object.fromEntries(formData));
  await db.user.update({ data });
}

API 路由安全

App Router(app/api/*/route.ts):

// ❌ 无鉴权
export async function GET(request: Request) {
  return Response.json(await db.users.findMany());
}

// ✓ 鉴权中间件
import { getServerSession } from "next-auth";
export async function GET(request: Request) {
  const session = await getServerSession();
  if (!session) return new Response("Unauthorized", { status: 401 });
  // ...
}

Pages Router(pages/api/*.ts):检查所有 handler 是否缺失鉴权。常见问题:GET 公开但 POST 有鉴权,导致不一致。

Middleware 安全

// middleware.ts
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

export function middleware(request: NextRequest) {
  const token = request.cookies.get("session");
  
  // ❌ 仅检查是否存在
  if (!token) return NextResponse.redirect("/login");
  
  // ✓ 应验证 token
  // 但 middleware 难以进行异步数据库调用!
  // 解决方案:使用 next-auth middleware 或验证 JWT
}

// 关键:检查 matcher 是否覆盖所有受保护路由
export const config = {
  matcher: ["/dashboard/:path*", "/admin/:path*", "/api/admin/:path*"],
};

Matcher 遗漏示例:

// ❌ 遗漏 API 路由
matcher: ["/dashboard/:path*"]
// /api/admin/* 下的管理 API 未受保护!

// ✓ 包含 API 路由
matcher: ["/dashboard/:path*", "/api/admin/:path*"]

响应头与安全配置

next.config.js:

// 检查安全响应头
module.exports = {
  async headers() {
    return [
      {
        source: "/:path*",
        headers: [
          { key: "X-Frame-Options", value: "DENY" },
          { key: "X-Content-Type-Options", value: "nosniff" },
          { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
          // CSP 较复杂——检查是否存在且不过于宽松
        ],
      },
    ];
  },
};

常见漏洞与严重程度

问题 检查位置 严重程度
NEXT_PUBLIC_ 密钥泄露 .env* 文件 CRITICAL
Server Actions 未鉴权 app/**/actions.ts HIGH
API 路由未鉴权 app/api/**/route.ts、pages/api/** HIGH
Middleware matcher 遗漏 middleware.ts HIGH
缺失输入校验 Server Actions、API 路由 HIGH
动态路由 IDOR [id] 参数缺少归属校验 HIGH
dangerouslySetInnerHTML 组件 MEDIUM
缺失安全响应头 next.config.js LOW

快速检索命令

# 查找 NEXT_PUBLIC_ 使用
grep -r "NEXT_PUBLIC_" . -g "*.env*" -g "*.ts" -g "*.tsx"

# 查找 next.config env 使用(始终会被打包)
rg -n 'env\s*:' next.config.*

# 查找无鉴权的 Server Actions
rg -l '"use server"' . | xargs rg -L '(getServerSession|auth\(|getSession|currentUser)'

# 查找 API 路由
fd 'route\.(ts|js)' app/api/

# 查找 dangerouslySetInnerHTML
rg 'dangerouslySetInnerHTML' . -g "*.tsx" -g "*.jsx"

适用场景

  • Next.js 项目代码审查与安全自查
  • 上线前检查环境变量、鉴权与 middleware 覆盖
  • 排查 Server Actions 与 API 路由的鉴权与输入校验问题

限制

资料未提供该技能的安装方式、运行环境要求、自动化程度、收费模式及具体平台支持信息,暂未提供。