面向 Next.js、Supabase 和 Stripe 应用的本地静态安全扫描器:24 项基于 AST 的检查,用于检测泄露的密钥、缺失的 RLS 和授权以及不安全的 webhook。提供 CLI 和 GitHub Action。
面向 Next.js + Supabase + Stripe 应用的免费本地安全扫描:泄露的密钥、缺失的 RLS 和授权、不安全的 Stripe webhook。
你的 AI agent 交付了应用。但它是否也一并泄露了你的 Stripe 密钥、留下了一张没有 RLS 的表,或者一个任何人都能调用的 webhook? 一条命令即可在本地、不到一秒内查明。
npx github:edtrackai/nextjs-supabase-stripe-security-checker /path/to/your/app
它还没有发布到 npm,因此 npx 会直接从该 GitHub 仓库运行它(需要 Node 18+ 和 git)。
- uses: edtrackai/nextjs-supabase-stripe-security-checker@v0
with:
fail-on: high
完整的工作流程和权限说明见下文以及 docs/github-action.md。
Supabase RLS 检查器 · Stripe webhook 安全 · Next.js 安全扫描 · Supabase Data API 授权(42501)

git clone https://github.com/edtrackai/nextjs-supabase-stripe-security-checker.git
cd nextjs-supabase-stripe-security-checker && npm install
node bin/nss-security-check.js /path/to/your/app
需要 Node 18 或更高版本。只有一个依赖(@babel/parser)。它免费且采用 MIT 许可证,无需账户,不发起网络请求,也绝不会上传你的代码。
--fail-on=high 会以退出码 1 退出,--json 提供机器可读的输出。广告(付费,同一作者): 想要修复方案?Launch Audit(12 美元,适用地区另加增值税)新增 28 项检查、一个不具备 Edit 或 Write 工具的 AI 审计代理,以及一份 file:line 修复计划。
| 标志 | 作用 |
|---|---|
--json | 机器可读输出:{tool, version, root, filesScanned, counts, findings[]} |
--fail-on=<sev> | 若存在等于或高于 critical / high / medium / low 的发现,则以退出码 1 退出(none 永不失败)。参数错误时以退出码 2 退出。 |
--list | 打印检查目录 |
--quiet | 省略关于付费工具的一行页脚(仅在终端上打印到 stderr;设置 NO_PROMO=1、CI 或 GITHUB_ACTIONS 时也会关闭) |
--help | 用法 |
在 CI 中:node path/to/bin/nss-security-check.js . --fail-on=high,或使用 GitHub Action(作业摘要、注解、一条固定的 PR 评论,仅需 GITHUB_TOKEN)。请参阅 docs/github-action.md 中的示例工作流和权限。
# .github/workflows/security-check.yml
name: Security check
on: [pull_request]
permissions:
contents: read
pull-requests: write # only for the PR comment; drop it with comment: false
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: edtrackai/nextjs-supabase-stripe-security-checker@v0 # or pin @v0.5.0 / a commit SHA
with:
path: .
fail-on: high
变更记录见 CHANGELOG.md(0.5.0 新增了 Action)。
| ID | 严重程度 | 领域 | 检查项 |
|---|---|---|---|
| K1 | critical | 密钥 | 源码中出现有效的 Stripe 密钥/受限密钥(sk_live_/rk_live_),包括用 + 拼接的密钥(证据已脱敏) |
| K2 | critical | 密钥 | 疑似密钥的 NEXT_PUBLIC_ 变量(service role、secret key、webhook secret……) |
| K3 | critical | 密钥 | .env 文件中的值被 git 跟踪 |
| K4 | critical | 密钥 | 在 "use client" 组件中使用了服务端密钥或 Supabase 管理客户端 |
| A1 | high | 认证 | 在服务端信任 auth.getSession(),而非 getUser()/getClaims() |
| A2 | high | 认证 | Server Action 写入数据时未做认证检查 |
| A3 | high | 认证 | API 路由(POST/PUT/PATCH/DELETE)写入数据时未做认证检查(webhook、cron 和认证路由除外) |
| A4 | high | 认证 | 用请求提供的 id 查询管理客户端且无所有者过滤(IDOR) |
| A5 | medium | 认证 | 由查询参数导致的开放重定向 |
| R1 | critical | RLS | 创建表时未启用行级安全 |
| R2 | critical | RLS | 写入策略使用 using (true) / with check (true) |
| R3 | high | RLS | 允许 anon 角色写入的策略 |
| R4 | high | RLS | security definer 函数未固定 search_path |
| R5 | medium | RLS | public 中的表没有显式 GRANT。Supabase 宣布将从 2026 年 10 月 30 日起停止对新 public 表的默认授权,但在 8 月下旬,一位 Supabase CLI 维护者写道(supabase/cli PR #6337),先前的默认变更“从未落地”,托管项目仍在自动授权,因此该日期可能会变动:请检查你自己的项目实际行为。没有授权时,Data API 会返回 42501 |
| R6 | high | RLS | 对 anon/authenticated 的一揽子 grant ... on all tables in schema public / alter default privileges ... grant(这是快速修复 42501 的做法,但同时会暴露未启用 RLS 的表) |
| S1 | critical | Stripe | Webhook 未验证签名(constructEvent) |
| S2 | critical | Stripe | Webhook 解析 request.json() 而非原始请求体 |
| S3 | medium | Stripe | Webhook 未对 event.id 做幂等处理 |
| S4 | high | Stripe | 结账价格或金额取自请求 |
| S5 | high | Stripe | 在结账成功页面授予访问权限,而非在 webhook 中 |
| S6 | medium | Stripe | Webhook 去重可能吞掉失败事件:跳过重复事件时没有 pending/completed 状态 |
| S7 | low | Stripe | 从 items.data[0] 读取计费周期(自 API 2025-03-31.basil 起,对多项目订阅是错误的) |
| H1 | medium | 加固 | next.config 中没有安全响应头 |
| H2 | medium | 加固 | dangerouslySetInnerHTML 使用了非字面量值 |
fixtures/vulnerable-app 会触发全部 23 项基于文件的检查,测试会断言每一项都出现在预期的文件中。K3 在临时 git 仓库上测试。fixtures/clean-app(一个加固过的参考应用)和 fixtures/near-miss(看起来像每种错误的安全代码:带 pending/completed 幂等的原始请求体 webhook、多项目安全的周期查询、带防护的重定向、按所有者过滤的管理查询、select using (true)、JSON-LD)必须产生 0 条发现。npm test 运行 node:test 测试套件,包括 CLI 标志和退出码。npm run smoke 给出一行摘要。requireUser*、getUser*、verifySession*、assertAuth*、auth()、currentUser() 和 protect() 命名的辅助函数会被识别。supabase/migrations 和 .sql 文件中的 SQL。在仪表板中创建的策略对它不可见。npm audit)或完整的 git 历史记录中的密钥(请使用 gitleaks)。广告:以下产品是同一作者(Stack & Ship)的付费产品。无论哪种方式,CLI 都保持免费并采用 MIT 许可证。
这个免费 CLI 只是一个小型子集。如果你即将发布:
在交互式终端上,人类可读输出会以 stderr 上的一行结束,标记为“Ad”,内容是关于同一作者的一款付费工具。具体是哪一行取决于发现结果:Supabase 授权发现(R5/R6)链接到 AI Rules v2 包,Stripe webhook 发现(S1/S2/S3/S6)链接到 Launch Audit,其他情况则同时链接两者。它是纯文本:CLI 不进行任何网络调用,也不收集任何遥测数据。它绝不会出现在管道、重定向报告(> report.txt)或 --json 中,并且在设置了 CI 或 GITHUB_ACTIONS 时关闭。可在任何地方使用 --quiet 或 NO_PROMO=1 将其隐藏。
npx skills add edtrackai/ship-ready-skills)。MIT