跳到正文
Chandler Nguyen
AI阅读时间2分钟

我在想 vibe coder 和维护这件事,然后检查了自己的应用

一条 Next.js 安全公告影响到我自己的三个应用。其中一个当月有 175 次提交,20 天后却还没打补丁,因为什么都没坏。这里是我发现的情况,以及我现在认为每个做产品的人都需要的几项小检查。

我在工作中一直和很多 vibe coder 共事,这让我开始思考维护这件事。软件上线之后还需要照看,依赖包会过时,漏洞会被发现,而刚开始用 AI 做东西的时候,很容易想不到这些。

后来我意识到,我也应该用同样的思路看看自己的项目,于是翻了它们的 git 历史。我发现了不少东西,只是和预想的不一样,其中还有一项在我查看的当天仍未解决。

所以这已经不是一篇讲别人忘了什么的文章了。它讲的是我自己。

一条公告,三个应用

10 月 14 日,Next.js 发布了两个严重(critical)漏洞和一个高危(high)漏洞的修复。这里的“严重”指远程代码执行,也就是说,在某些条件下,互联网上的陌生人不用登录就能在你的服务器上运行自己的代码。修复包含在 16.4.1 版本中。

我有三个应用跑在 Next.js 上,都是用 AI 编程工具做的,负责人也都是同一个人,就是我。情况是这样的:

应用代码何时升级到已修复版本公告后过了多久上线生产环境
chandlernguyen.com10 月 18 日4 天10 月 18 日
DIALØGUE(对话)10 月 29 日15 天10 月 29 日
Prova11 月 3 日20 天11 月 3 日

我在 11 月 3 日查看时,Prova 还锁定在 Next.js 16.2.6,也就是它从 5 月起一直用的版本,生产环境跑的也是它。运行 pnpm audit --prod 列出了 5 条严重公告,全都在 Next.js 里。

这个数字听起来比我实际发现的情况更糟,所以我想说得公平一点。我和 AI 工具逐条过了一遍,大部分严重公告并不适用于 Prova。它没有 use cache 函数,不在 Windows 上运行,我也没有发现攻击者能控制的输入可以到达 next/og 代码。图片优化相关的几条在 Vercel 上可能也不适用,不过这是我根据平台行为做的推断,因为我没有找到 Vercel 这样说的声明。明确适用的是 Server Actions 中一个高危的拒绝服务问题,也就是说有人本可以干扰这个应用,而这个问题一直存在到打补丁为止。

我当天就把生产环境升级到了 Next.js 16.4.5。audit 的结果从 5 条严重降到 0 条,大部分高危也消失了。剩下的都在 Next.js 之外,我还得继续处理,所以是好多了,但还不干净。

这些都算不上好的维护。最严重的公告大多没打到 Prova,是因为它碰巧是这样构建的,而不是因为有人检查过。这是运气,而我知道这一点,也只是因为我终于去看了。

表格第一行我也不敢太居功。我网站 10 月 18 日的提交是一次常规的工具链升级,从 Next.js 16.1.6 升上去,提交信息里根本没提这条公告。也许只是时机碰巧不错。

为什么忙碌没有帮上忙

最容易的解释是 Prova 被冷落了,这也有几分道理。8 月到 9 月之间,它有过 41 天的提交空档。

但这个解释到 10 月就站不住了。Prova 那个月有 175 次提交。我发布了 iOS、计费、邮件和翻译方面的修复,而 Next.js 版本一动没动。10 月 30 日,我甚至写了一份依赖维护计划。它的状态行写着:“已计划;尚未开始实施。”

所以活跃不等于维护,我认为这是对每个用 AI 做东西的人来说最重要的一点。做一个功能,你马上就能得到反馈。你能看到按钮,点一下,看着它运作。而你五个月前安装的包被公布了漏洞时,你什么反馈都得不到。应用照常提供页面,测试一片绿,构建也能通过。什么都没坏,也正因为如此,没有人去看。

这就像一个只有你跑过去问它才会响的烟雾报警器。AI 工具让盖房子便宜了很多,但它们不会帮你装报警器。

这种事以前也发生过。DIALØGUE 在 2025 年 10 月 6 日到 2026 年 1 月 11 日之间没有任何提交。React2Shell 是 Next.js 和 React 的一个严重漏洞,在 12 月初公开。我的补丁提交日期是 1 月 11 日,晚了五周多,而我现在还能看到的最早生产部署记录是 1 月 18 日的,所以我没法确切告诉你 12 月跑的是什么。最帮得上我的很可能和我毫无关系:Vercel 说它为所有客户部署了防火墙规则,同时也明确表示不要依赖这些规则来代替打补丁。

有一点我想说清楚,因为“vibe coder”这个词听起来可能像在骂人。我是通过系统的课程学会编程的,其中包括一个网络安全证书,这些代码库也有测试和审查关卡,可是这事还是发生了。所以我不认为这是新手的问题。我认为,当做软件变得便宜、又没有人被指定去看着它时,默认就会发生这种事。

报警器长什么样

好消息是,一个很小的检查就能大大改变这一点。

10 月 27 日,我把 pnpm audit --prod 加进了网站的 CI,也就是推送代码时自动运行的那组检查。10 月 28 日它失败了,原因是一个邮件渲染库的安全公告,我的网站引入了这个库却从未用过,10 月 29 日我把它移除了。前后两天,我什么都不用记。

这里面没有任何巧妙之处。只是必须有人,或者有什么东西,被安排去看。

更新依赖包救不了我

如果这篇文章到此为止,只会给你一种虚假的安心,因为我 10 月做的修复里,有些更让人不舒服的修复和过时的依赖包毫无关系。那是我自己产品里的错误。

比如在 DIALØGUE 中:

  • 有特权的数据库函数只用公开密钥就能调用,已登录用户也能碰到本来只给我的后端用的函数。
  • 已退款的播客可能会“复活”,并在没有再次扣费的情况下完成,而且确实有少量播客发生过这种情况。

在 Prova 中,公开的数据库角色继承了没有人选择过的权限,比如 TRUNCATE,因为它们来自平台默认设置。应用里没有任何路径用到它们,但它们就在那里。

任何版本升级都修不了这些。这些应用带着这些问题一直在运行,这里同样什么都没坏。它们之所以浮出水面,只是因为一次安全审查专门去找了,而我之前对这些产品做过的安全审查并没有把它们全部找出来。

这些问题有被滥用吗?我不知道,也无法完全查清楚。我的数据库日志只能回溯大约 90 天,而其中一些问题比这更早。在我能看到的时间段内,我没有发现外部对那些函数的调用。这只覆盖了有限的时间窗口,并不能说明什么都没发生。我也说不清是谁或什么重启了那些已退款的播客,不过我最好的猜测是我自己代码里的一次重试。

这也不是一份完整的清单。我还在处理其他问题,在它们解决之前我不会描述。

模型的问题和我以为的不一样

我本来打算写,旧的 AI 模型会让你多花钱。我没法证明这一点。我查过了,这些代码库里都没有前后成本的对比,所以那只是猜测。

我发现的情况更奇怪。DIALØGUE 的脚本草稿和审查模型,在 10 月 12 日之前都设置为 gemini-3.5-flash。Google 的文档现在说,这个端点不会关闭,并会自动把请求转到 gemini-3.6-flash。我不知道这种转发是什么时候开始的,所以没法告诉你到底是哪个模型回答了多久。配置里写着模型名称,并不能把模型固定住。

价格也会变。Gemini 3.8 Flash 是我在 10 月把 Prova 和 DIALØGUE 迁移过去的模型,截至 12 月 31 日的标价是每百万输入 token $0.75、每百万输出 token $3.75。从 2027 年 1 月 1 日起翻倍,变成 $1.50 和 $7.50。我上个月才迁移过去,还得算一算这对我的成本有什么影响。

升级也不是没有风险,我不想假装没有:

  • 我把 Ask Sydney(悉尼)切换到 DeepSeek Flash 后不久,生产环境里至少有一次提问失败了,因为模型想要的搜索轮数超过了我代码允许的上限。
  • 我迁移 Prova 的 embedding 时,最初几次运行在知识库表被清空之后失败了,所以检索质量一直下降,直到我恢复为止。
  • 同一次迁移还发现了一个生产设置,它本来会把 Claude 的模型名称发给 Google 的 API。

让 Prova 这次迁移值得信任的,是件很无聊的事。我有一份改动前记录的评估,24 个冲刺评审决策里对了 22 个,改动后得到了同样的分数。没有它,我就只能靠祈祷。

你到底该不该维护它?

最难的问题,是我差点漏掉的那个。你发布的每个应用,都是一份要用注意力持续付费的小订阅,而 AI 让再多订几份变得非常容易。

在 STRAŦUM(斯特拉图姆) 上,我做了另一种选择。我把它退役了,并把 v1 作为参考实现发布。代码库写明它不作为生产服务维护,安全文件列出了我知道的公告,其中包括一些构建阶段的依赖问题,目前没有修复方案,并评估为实际风险较低。我认为这是一个完全诚实的结果。不诚实的版本,是一个没人看管却还在接受注册的应用。

周一我会做什么

如果你用 AI 发布了东西,而且有人在用,我会从这份清单开始。每一项都不需要完美。

  1. 今天就运行一次 audit。 在每个线上的代码库里运行 npm audit --omit=dev 或 pnpm audit --prod。然后问你的 AI 工具,哪些结果适用于你应用的构建方式,因为不会全都适用。
  2. 让这项检查自动化。 把它加进 CI,这样不用你记着它也能失败。对于很少碰的应用,还要加上定时运行,因为只在推送时运行的检查,在安静的月份帮不上忙。
  3. 读你的权限,而不只是依赖包。 问问自己:只拿着你的公开密钥、没有账号的人能做什么。然后在本地副本上测试,不要靠假设。
  4. 在历史记录里搜索密钥。 如果曾经提交过真实的密钥,就把它吊销。只删掉那一行是不够的。
  5. 在需要之前,先弄清楚你的日志能回溯多久。 这决定了你是否有可能回答“有没有东西被滥用”这个问题。
  6. 为每个 AI 功能保留一个小评估。 哪怕只有 20 个已知好答案的真实例子,也能告诉你换模型有没有让情况变差。
  7. 定期查看 AI 服务商的弃用和价格页面。 把它放进日历。如果你在用 Gemini 3.8 Flash,就先把 1 月 1 日标进日历。
  8. 为每个应用决定留下还是退役。 如果你不打算看着它,就把它下线,或者说清楚。

我还在摸索这些事情有多少可以定时交给 agent。我确实知道的是,10 月 30 日写的那份计划,什么也没修好。

如果你在用 AI 做东西,你上一次检查已经发布的东西是什么时候,发现了什么?我真的很想知道,尤其是如果你有比我更好的报警器。