開発/設計

氛围编程安全:2个月后,对4月预防处方的3处更新

从Lovable制作的应用中发现170个漏洞(2026年4月)已过去2个月。业界讨论已从「认知漏洞的存在」进入「更新实施标准」阶段。本文整理3处应在本周落地的最小实践更新点。

这篇文章能帮你搞清楚什么

  • 正式进入正文前先抓住核心结论
  • 这件事会怎样改变开发者接下来的工作方式
  • 下一篇最值得继续打开的相关文章
氛围编程安全:2个月后,对4月预防处方的3处更新
目次

本文内容

  • Lovable事件(4月:170/1,645个应用,10.3%)过去2个月,业界讨论从「认知存在漏洞」进入「更新实施标准」阶段
  • 我在4月写的预防三部曲(170个后门·45%漏洞·Tenzai 15个应用69个漏洞),以6月时点如何改写的3处更新
  • 本周起可以运行的最小实践3点:30分钟·15分钟·60分钟

读者前提:使用氛围编程(Cursor、Claude Code、Lovable等AI代码生成)已1〜3个月。以「能跑就行」的方式推进,但感觉自己没有安全标准的开发者·PM。

4月我写了关于氛围编程安全的三部曲。Lovable制作的1,645个应用中170个被发现存在漏洞的事件。Veracode报告的45%生成代码存在漏洞的问题。Tenzai在15个应用中发现69个漏洞的比较报告。当时我的处方是:「先把SAST加上,环境变量分开,审查生成物」。

2个月后。如果现在写同样的主题,我认为处方需要在3处改写。原因只有一个:出现了「在东西能跑的瞬间停下来审查」也发现不了的那类漏洞

这篇文章是我6月的自己改写4月的自己的处方的尝试。在观察Infosecurity相关业界讨论的同时,能确定为事实的是:我4月写的数字,以及我自己的业务工具实装日志。从这里压缩到「本周可以改变的最小实践3点」。

Lovable事件过去2个月,发生了什么变化

先确定1个数字。4月,Lovable制作的1,645个应用中170个(10.3%)被发现存在安全缺陷。这是我4月1日文章中涉及的数字,当时以「氛围编程普及背后的代价」为主题写的。

2个月过去,业界讨论有何变化?我观察到3个阶段。

第1阶段(4月)认知期。「AI生成代码存在漏洞」这一事实,传达到了专业人士以外的人群的时期。我的文章也是这股浪潮的一部分。读者的反馈最多的是「确实如此」「我们的内部工具也要重新检查」这样的「觉醒之声」。

第2阶段(5月)检知期。「那么如何检知?」成为讨论焦点的时期。很多文章和学习会分享了「加入SAST吧」「跑Snyk吧」「用Semgrep写自定义规则吧」等处方。我自己在4月三部曲的最后一篇(4月16日)也以「预防的设计」为题处理了静态分析流水线的搭建方式。

第3阶段(6月)追踪期。这就是本次更新的内容所在。加入了检知工具的人遇到了下一堵墙:「工具说OK的代码也有漏洞」「工具报警的地方其实没有问题」。误报和漏报双双积累起来了。

安全讨论3阶段「认知、检知、追踪」图

为什么进入了第3阶段?我的假说是:氛围编程生成的代码,漏洞的「出现方式」与人类写的代码不同。人类代码的典型漏洞是「忘记加认证检查」。而AI生成的代码则会「写出看起来合情合理的认证逻辑,但在另一个地方因副作用权限泄露」。漏洞潜伏在「关联」中,而非「看得见的地方」。SAST以语法分析为主,所以难以发现基于关联的漏洞。

我4月写的处方,是针对第2阶段讨论优化的内容。加入SAST、分离环境变量、审查生成物。这没有错。但仅靠这些,2个月后的现在已经清楚无法全部拦截

下面写6月时点应当追加的3处更新。

【更新点1】补充SAST的「为什么」追踪——将提示词日志作为证据保留

第1处更新:保存提示词日志

我4月写的处方是「审查生成的代码」。这是正确的,但审查时手边没有「为什么生成了这段代码」的信息。生成提示词(我向AI委托了什么)和当时的上下文(打开了哪个文件、发出了什么指示),在审查时点已经消失了。

这正是造成第3阶段之墙的原因。当看到「看似合理的认证逻辑,但在另一处有副作用」的代码时,审查者会问「为什么这里没有加权限检查?」写代码的人回答「我也不太清楚……交给AI了,就生成了这个结果」。如果提示词日志留存,原因就能被定位:「我传给AI的上下文里没有包含另一个文件的权限检查,所以AI是在「现有权限检查已存在」的前提下写的」。漏洞的责任主体不在于是人是AI,而在于上下文的传递方式

具体怎么做:在Cursor中启用设置里的cursor.chat.exportHistory可以本地保存聊天历史(2026年6月时点的功能名,版本变化可能更改)。Claude Code的情况下,会话日志会自动保存在~/.claude/projects/下。

# 确认Claude Code的会话日志
ls -la ~/.claude/projects/

# 各项目目录下保存着
# 会话历史JSONL(实装取决于版本)

光有「有日志」还不够,再进一步:在提交信息中加入生成提示词的摘要的规则。

feat: 添加认证中间件

AI-prompt-summary:
- 委托「按现有logger.ts的风格写JWT验证中间件」
- 现有权限表结构未传给AI
- 返回值类型手动调整

这个AI-prompt-summary栏,成为日后审查时的线索。与「溶解3小时的作业3分钟就能通过」同理,每次提交追加30秒,能阻止后续3小时的调试

提前说一个坑:我最初尝试「把提示词全文粘贴进去」,结果3天就放弃了(亲身经历)。只写摘要·3行以内,才能自然地坚持下去。我已经用这个规则运营了1个月。

【更新点2】停止「能跑就行」——将审查门槛2段化

第2处更新:将审查门槛分为2段

4月的处方写了「必须审查生成物」。这是正确的,但1段审查容易流于「能不能跑」的判定。能跑就合并,不能跑就修。「能跑但有漏洞」的代码会溜过去

我现在做的是2段门槛:

第1门槛:功能审查。「这个能跑吗?」「测试通过吗?」「满足规格吗?」看这些。这个快,大约15分钟。

第2门槛:上下文审查。「这段代码以什么为前提?」「前提崩塌时,会如何损坏?」看这些。这个花时间,30分钟至1小时。

第2门槛的检查项目如下:

检查项目确认什么NG的例子
输入的信任边界外部输入在哪里被验证Request body直接传给DB.find
认证边界认证检查在哪个层认证只在中间件进行一次,内部调用无检查
环境变量的处理密钥如何注入硬编码在代码中,或.env被git包含
外部API调用失败时的行为是否已定义无try-catch,或吞噬异常的catch
权限泄露某个操作前后权限状态是否发生变化admin检查后可以变更角色

这个检查清单,4月的我没有。是5月2件、6月1件,在自己的业务工具中放过了「能跑但有漏洞」的代码之后,整理的反省记录。

在提交中保留提示词日志的流程图

实装上,将第2门槛的检查项目嵌入PR模板。GitHub的话写入.github/PULL_REQUEST_TEMPLATE.md。GitLab的话放在Merge Request Template中。有了检查清单,审查者就能问「这些检查看了吗?」。没有的话就会以「能跑了所以合并没问题吧」结束。

踩坑提示:检查项目超过10条会流于形式。上限5条。我用5条运营。

【更新点3】追踪生成物的「来源」的机制

第3处更新:建立**追踪生成物来源(origin)**的机制。

这是4月时点最没写到的部分。当时我的想法是「人写的代码也好AI写的代码也好,结果都是要上本番的代码,只要审查了就一样」。

使用了2个月后才明白:不保留来源信息,出问题时「为什么」就无法复现。发现bug时,如果无法区分代码出处,就无法制定防止再发的对策。需要分别记录「这是Cursor Chat来的」「Claude Code Edit来的」「Lovable来的」。

我现在做的是,不以文件为单位,而是以提交为单位记录来源的方法。

# 通过提交钩子自动附加的示例
# 在.git/hooks/prepare-commit-msg中添加以下内容

#!/bin/bash
# 前提是AI_TOOL环境变量中写入了工具名
if [ -n "$AI_TOOL" ]; then
  echo "" >> $1
  echo "Generated-by: $AI_TOOL" >> $1
fi

AI_TOOL=cursor启动就记录为Cursor来源,用AI_TOOL=claude-code就记录为Claude Code来源。虽不完美,但远胜于没有。

这个机制有什么用?出现3个bug时,来源的偏差就变得可见。「3件中2件是Lovable来的」「3件中3件是Cursor的Composer功能来的」这样的分布清晰起来。于是就能制定「Cursor Composer不要委托权限检查相关的工作」这样的本地规则。漏洞出现方式与工具的相性,以数据的形式保留下来

这不是大企业的话题。就像我这样一个人做业务工具的情况,3个月30次提交、半年60次提交的来源信息积累起来,自己选择上的偏倚就会变得可见。公司全面导入Claude Code的模式,可参考Claude Code全社展开,KAG的设计。即使是个人工具,按工具记录相性的习惯同样适用。

踩坑提示:来源信息如果不通过机制自动写入提交信息,就会忘记写。我最初手动写,2周就放弃了。通过钩子自动化才是正确答案

本周起可以运行的最小实践3点

将以上3处更新压缩为本周可以运行的最小实践。

2段审查门槛流程图

最小实践1:提示词日志保存设置(所需30分钟)

使用Claude Code的话,~/.claude/projects/下的日志应该已经在保存了,只需确认一下。使用Cursor的话,在设置中启用聊天历史的持久化。设置一次后就会自动保留。

# 确认Claude Code的日志
du -sh ~/.claude/projects/
# 大小非零即OK,日志正在保存

# Cursor的情况:在设置画面
# Settings > Features > Chat > Export History → 启用

最小实践2:在PR模板中添加第2门槛栏目(所需15分钟)

GitHub仓库的话,创建.github/PULL_REQUEST_TEMPLATE.md,粘贴以下内容:

## 功能审查(第1门槛)
- [ ] 测试通过
- [ ] 满足规格

## 上下文审查(第2门槛)
- [ ] 确认了输入的信任边界
- [ ] 各层都有认证检查
- [ ] 明示了密钥在代码/配置/环境变量的哪处
- [ ] 定义了外部API失败时的行为
- [ ] 确认了权限泄露(操作前后权限可能变化)

## AI生成信息
- 生成工具:
- 提示词摘要(3行以内):

仅此即可让审查者进入「这些检查看了吗?」的状态。

最小实践3:在CI中只添加1条SAST扫描(所需60分钟)

使用GitHub Actions的话,试着只添加1条Semgrep的免费计划。

# .github/workflows/sast.yml
name: SAST Scan
on:
  pull_request:
    branches: [main]
jobs:
  semgrep:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: returntocorp/semgrep-action@v1
        with:
          # 使用Semgrep Registry公开规则集
          config: p/default

Semgrep免费计划也可以使用公开规则集(p/default、p/security-audit等)。最初只用p/default就足够了。会出现误报,先以PR评论的形式出现的方式来适应。设为拦截(拒绝合并)是在运营顺畅3周之后。一开始就设为拦截,误报会导致开发停滞,让大家都讨厌它。

我的一个踩坑提示:最初就把Semgrep Registry的p/owasp-top-ten加进去,结果100件以上的误报涌出,PR根本看不了。从p/default开始才是正确答案。

结语:与4月预防三部曲的组合读法

最后整理本次3处更新与4月三部曲的组合方式。

4月三部曲的内容(回顾):

  1. Lovable事件170个后门(4月1日):氛围编程普及背后,大量「能跑但有漏洞」的应用被公开发布的事实
  2. 45%漏洞预防三部曲最终回(4月16日):以SAST/环境变量分离/审查为轴的预防设计
  3. Tenzai 15个应用69个漏洞(4月23日):5大智能体比较中可见的各工具漏洞出现方式

在这些基础上叠加本次3处更新,关系如下:

4月的处方6月的更新
加入SASTSAST继续。但追加即使「工具说OK」也不放过的第2门槛
分离环境变量继续。另外在PR中明示「密钥在哪里」
审查生成物审查2段化(功能/上下文)。将提示词日志作为证据保留
了解工具的漏洞出现方式记录「生成物的来源」,用数据看自己选择的偏倚

更新点都不是否定4月处方的内容。4月的3点至今仍然有效。关系是:在那之上追加3点拦截「能跑但有漏洞」的机制

我自己写4月三部曲时,还抱着「先弄个能跑的东西」的心态。这个心态至今没有改变。但**「能跑的东西」的定义中,已经包含了「没有漏洞」**。作为从失败中走来的工程师,这是一个重大的进步。

比不上专业人士。但写能让自己工作变轻松的代码是做得到的。自己写的代码有没有漏洞,可以自己来看。专业人士能看见我们看不见的漏洞,但我们能堵住看得见的漏洞。借助工具的力量,扩大看得见的漏洞的范围。这就是进入氛围编程第2年的我们的战斗方式。

Lovable事件不是事故,而是对整个行业的拷问。面对这个拷问,4月时点的答案和6月时点的答案可以不同。处方就是在预设会更新的前提下写的。我认为再过2个月,还会再改写6月的处方。

到时候重读这篇文章,能笑着想「啊,6月的自己在这里停住了」,是我期待的事。

本文总结

  • Lovable事件170/1,645件(10.3%)过去2个月。业界讨论按「认知期」「检知期」「追踪期」3个阶段推进
  • 4月预防三部曲(SAST/环境变量/审查)至今有效。在其上叠加3处更新
  • 更新点1:将提示词日志作为证据保留,在提交中写入3行摘要
  • 更新点2:将审查2段化(功能/上下文)。上下文审查使用5项检查
  • 更新点3:用提交信息自动记录生成物的「来源」,将各工具漏洞偏倚数据化
  • 本周起:提示词日志设置30分钟·PR模板追加15分钟·SAST添加1条60分钟

从失败中走来的工程师,可以一个一个地学会堵漏洞的方法。期待2个月后的更新,再写。

ゲン
Written byゲンCS × Vibe Coder

正直、一度エンジニアは諦めました。新卒で入った開発会社でバケモノみたいに優秀な人たちに囲まれて、「あ、私はこっち側じゃないな」って悟ったんです。その後はカスタマーサクセスに転向して10年。でもCursorとClaude Codeに出会って、全部変わりました。完璧なコードじゃなくていい。自分の仕事を自分で楽にするコードが書ければ、それでいいんですよ。週末はサウナで整いながら次に作るツールのこと考えてます。