ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

AI写代码时代,如何给代码安全套上四条缰绳

AI写代码时代,如何给代码安全套上四条缰绳 最近半年我一直在高强度地用 AI 写代码效率提升确实实打实。但真正让我警觉的是一次 Review同事用 AI 生成的 1200 行 Merge Request逻辑通顺、注释齐全可里面那个文件上传接口没有任何类型校验——意味着任何人都能把任意文件丢到我们的服务器上。代码能跑和代码安全是两码事。我越来越确信一个判断AI 写代码越快越要先把安全缰绳套上。这篇文章就把我沉淀下来的几条底线完整梳理一遍不绕弯子全是能直接落地的做法。1. AI写代码为什么越快越危险三条被多数人忽视的放大效应先别急着上措施得先搞清楚风险是如何被放大的。很多人以为 AI 写代码的危险在于它可能写出错的代码这个理解太浅了。真正的危险是下面这三条它们叠加起来会让同样数量的代码产生远超以前的安全敞口。1.1 自动化偏见AI生成代码天然自带可信光环自动化偏见是个认知心理学概念最早在航空领域研究比较多——飞行员在自动驾驶仪工作时更容易忽略仪表盘的异常读数。程序员面对 AI 生成的代码完全是一样的心理机制。AI 写出来的代码语法工整、命名规范、注释完整甚至连变量名都能起得恰到好处。这种看起来很专业的外表会直接压过你的警觉系统。大脑会下意识觉得既然格式这么严谨逻辑大概率也没问题。再加上很多 AI 生成的代码确实能一次通过单元测试这种它可以正常工作的体验会进一步强化信任。我自己也栽过。有次让 AI 写一个登录接口功能测试全过但我后来仔细一查才发现没有频率限制、没有防暴力破解、密码重置 token 用的是不安全的随机数生成方式。AI 不是不会写这些防护而是它觉得需求描述里没写就没必要多事——它更倾向于生成一个看起来满足需求描述的最小可运行版本。这条认知是所有安全措施的心理基础你必须默认 AI 生成的代码是带病上岗的而不是默认它基本没问题。这个心态不转变后面所有流程都是摆设。1.2 概率错觉AI给的不是验证过的代码只是近似答案大语言模型的本质不是编译器而是下一个 token 预测器。它生成代码的过程是在概率空间里挑选一串最像正确代码的文本序列而不是像编译器那样经过语法、类型、数据流分析后给你一个可验证的结果。这个区别极其关键。因为训练语料里既有大量正确代码也有大量漏洞代码AI 对这两种模式同样熟练。当需求描述得不够具体时它很容易滑向训练数据中出现频率更高的捷径写法——字符串拼接 SQL、关闭 SSL 验证、使用弱加密算法。这些写法在开源项目的历史提交里太常见了AI 学得比谁都扎实。所以你会发现一个诡异的现象AI 写代码出漏洞往往不是那种明显语法错误而是格式完全正确、逻辑方向也差不多、但安全细节集体缺失的漏洞。这种漏洞最难被肉眼发现因为它不像报错那样会主动提醒你。1.3 攻击面扩张效率翻倍的另一面是风险敞口翻倍用 AI 写代码团队在同样时间内的产出可能翻两三倍代码库的膨胀速度也远超从前。攻击面是跟着代码量走的——每一行新代码都意味着新的输入点、新的依赖、新的执行路径可能被攻击者利用。代码量翻倍攻击面大体上也翻倍。更麻烦的是人的审查精力是有限的。以前一天写 200 行代码你有足够时间逐行品味现在 AI 一天帮你生成 800 行你能分配给每行代码的关注度直接降了一大截。这相当于风险敞口扩大了而防护注意力反而被稀释了。两条曲线一交叉事故率不涨才奇怪。从这个角度看安全措施的本质不是去限制 AI 发挥效率而是用自动化手段把人从细节审查中部分解放出来把注意力集中在 AI 最不擅长的语义判断上。2. 第一根缰绳从模型输入侧掐断敏感信息泄漏安全缰绳有很多条但第一根必须套在输入上。很多人只盯着 AI 输出的代码有没有漏洞却没想过一个问题你把什么东西喂给了 AI这一侧一旦失控代码漏洞都是小事了直接就是公司核心资产的泄漏。2.1 给AI划定上下文边界别让模型看到不该看的东西目前主流的 AI 编程工具无论是 ChatGPT 的 Codex、Cursor、GitHub Copilot还是国产的通义灵码普遍会读取当前工作区的上下文来辅助生成代码。你打开的每个文件、选中的每段代码、写下的每个 prompt都可能被送入模型。我见过的事故不在少数有人顺手把生产环境的数据库连接串粘进对话窗口问 AI帮我看看这段配置对不对有人让 AI 改造一个模块结果把包含内网拓扑的注释全部暴露给了模型。哪怕企业版承诺不用于训练这些数据也经历了一次出网——而这个出网友好不友好你根本控制不了。所以铁律第一条允许 AI 读取的项目目录必须明确划分。在 Cursor 里有 .cursorignoreCopilot 有代码排除配置GitHub 的仓库可以设置哪些路径不参与代码补全。把包含生产配置、客户数据、私钥证书的目录全部排除出去。同时要做团队约定凡是含密钥、口令、Token 的内容一律不允许出现在对话输入框里。AI 不需要看真实密钥也能帮你写代码它需要的只是结构、字段名、格式这些都可以脱敏后提供。2.2 密钥扫描前置AI生成的配置代码必须过硬校验AI 见过大量密钥格式它会自动补全看起来像密钥的字符串甚至在请求配置文件时顺手生成一个假 AWS Access Key 占位。单个假密钥没问题怕的是它把上下文里真实存在的密钥直接写进代码——因为 ChatGPT 这类工具的上下文确实包含了开发者本地的部分信息。对付这个问题靠自觉不够得上工具。我最常用的两个是 gitleaks 和 trufflehog两者都能在代码里扫描出高仿密钥格式的字符串。做法是把它们挂进 pre-commit 钩子任何包含疑似密钥的提交直接拒绝落盘。这样 AI 生成的代码还没进 Git 历史就被拦住了。配置很简单一个 .pre-commit-config.yaml 就能搞定repos: - repo: https://github.com/gitleaks/gitleaks rev: v8.18.4 hooks: - id: gitleaks实测下来的感受是这个钩子的价值不只是拦截泄漏更在于强迫开发者形成一个习惯——AI 生成的代码副本在人工确认密钥之前不允许进入主分支。2.3 团队级统一配置别让安全开关留在个人手里很多人不知道AI 编程工具的安全功能是可以被统一锁定的。GitHub Copilot 的企业版可以配置策略强制补全排除某些路径Cursor 的团队版也能在组织层面关闭某些隐私选项。这是最省力的一根缰绳但绝大多数团队根本没用起来。我建议技术负责人花一个下午做三件事第一把 AI 工具的隐私选项统一开启禁止个人关闭遥测采集第二把公司内部代码仓库中敏感目录放进排除名单第三规定所有 AI 辅助工具必须走企业账号严禁员工用自己的个人账号登录——个人账号的数据流向你完全不可控。这三件事做完至少能保证AI 在团队内输入侧的边界是统一且最小化的。安全管理的核心原则永远是集中管控优于个人自觉AI 工具链也不例外。3. 第二根缰绳第三方供应链审计AI的依赖记忆必须被约束AI 写代码对第三方依赖的使用量远超人类开发者。它动辄帮你引入几个库、几十个传递依赖而它记忆里的依赖版本号往往早就过时了。这一节说的就是供应链侧的缰绳。3.1 AI的记忆版本与最新稳定版本往往差了好几年大模型的训练数据有截止日期它对某个框架、某个库的权威版本认知可能停留在两三年前甚至更早。实际使用中它给你写个 pip install flask1.0而这个版本早已停止维护公开 CVE 列表长得能写一篇论文。更有意思的是AI 倾向于引用它训练数据中出现频率最高的写法。比如在 Python 生态里它可能给你塞一个 2018 年就标记为 deprecated 的库仅仅因为它在语料里见得多。你如果不主动去查这个包的维护状态和已知漏洞这段带病代码就直接进入生产环境了。所以针对 AI 生成的代码依赖审计的优先级要在所有安全检查里排到前面。人眼很难记得住每个库的哪个版本有什么漏洞这件事必须交给工具。3.2 生成SBOM给代码仓库建一棵食材清单SBOM软件物料清单这个概念通俗理解就是给代码仓库开一张食材清单——你在菜里用了哪些原料、每种原料是哪个厂家、哪个批次。没有这张清单等出事了你都不知道该查哪个供应商。生成 SBOM 的工具已经很成熟了syft 可以扫容器镜像和文件系统直接产出 CycloneDX 或 SPDX 格式的清单cdxgen 可以扫描几乎所有语言的工程文件。我建议在 CI 里加一个步骤每次构建都自动生成一份 SBOM 并提交到制品库。这样每个上线版本依赖了哪些组件版本号是什么有没有已知漏洞都有一份可审计的档案。这个动作看起来费时但真到了要响应第三方漏洞通报、排查线上环境受影响范围的时候你会发现有一份 SBOM 简直太救命了。3.3 CI里挂依赖漏洞扫描把过期组件挡在合并前SBOM 是静态档案依赖漏洞扫描是动态检查。两者配合才完整。常见的工具组合是 osv-scanner、pip-audit、npm audit它们会拿项目依赖清单去比对公开漏洞数据库一旦发现存在已知 CVE 的组件就报警。我的做法是在 GitLab CI 或 GitHub Actions 里加一条独立 job专门跑依赖扫描任何高危漏洞存在时直接 fail 流水线。给你一个 osv-scanner 的 GitHub Actions 示例name: dependency-scan on: pull_request: jobs: osv-scanner: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 - uses: google/osv-scanner/actions/scannerv1 with: fail-on-vuln: true配了这个之后AI 生成的旧版本依赖在合并前就会被自动拦下。同时要注意项目必须锁定依赖的精确版本——requirements.txt、package.json 里凡是出现、^、~这类范围符号的必须改写成具体版本号。锁文件要提交入库这样 AI 再怎么发挥想象力实际安装的依赖也跑不出锁定范围。4. 第三根缰绳面向AI代码的强人工审查与自动化门禁AI 写代码越多审查流程越不能省但审查的方式必须改变。传统那套 Code Review 习惯说实话挡不住 AI 代码的洪流。4.1 传统Code Review为什么挡不住AI代码传统 Code Review 依赖两个假设第一代码是作者自己写的作者对逻辑有完整上下文第二提交量在人类可处理范围内。AI 生成代码把这俩假设都打破了——AI 对业务上下文的理解是碎片化的而提交量又动辄几百上千行。更要命的是确认偏差。Reviewer 面对的是格式完美、注释齐全的 800 行代码大脑会自动开启欣赏模式而抑制挑错模式。几个研究都提到过人面对机器生成的高质量文本时发现错误的概率会显著下降。这意味着传统人工审查对 AI 代码的效率是断崖式下跌的。所以你需要建立一套专门面向 AI 生成代码的审查流程它跟普通代码审查有三点不同审查重点不同、审查辅助工具不同、合并门槛不同。4.2 一份可以直接抄的AI生成代码安全Review清单我建议团队在 PR 模板里加一个AI 生成代码专项检查区每次合并前逐项打勾。下面这份清单是我实际在用的可以直接抄走检查维度具体核对项常见AI问题认证与授权接口是否有身份验证、操作是否有权限校验只写功能实现完全跳过鉴权输入校验所有用户输入是否在服务端二次校验前端过滤就默认安全或根本不校验文件上传类型、大小、内容检查、随机重命名直接使用原始文件名无类型白名单数据库操作是否使用参数化查询习惯性字符串拼接 SQL敏感信息日志、报错、返回体是否泄漏密钥/堆栈exception 直接抛给前端依赖来源引用的包是否存在、版本是否陈旧臆造包名或引用过时版本错误处理失败路径是否有兜底只写 happy path异常直接爆数据合规数据存储位置、日志留存是否符合规范默认存本地不考虑合规要求这个清单执行起来有个技巧让提交代码的人逐项截图勾选而不是直接说已检查。截图会强迫他真正去看代码而不是在意识流里给自己发一张通过卡。4.3 让机器先拦一道SAST门禁的策略与阈值人工审查的精力有限所以前面必须有一道机器关卡挡住低级问题。静态应用安全测试SAST工具在这里最合适我常用的有 Semgrep 和 CodeQL它们能在不运行代码的条件下扫描出注入、硬编码凭据、危险函数调用等问题。关键点在于怎么设门禁。我的建议是CI 里 SAST 扫出的高危问题直接 fail 流水线不允许合并中低危必须清零或由安全负责人签字确认。给一个 Semgrep 在 CI 里的基本配置steps: - uses: returntocorp/semgrep-actionv1 with: publish_token: ${{ secrets.SEMGREP_APP_TOKEN }} fail_on: critical, error很多人会担心误报太多导致团队麻木。这个问题的解法不是关掉规则而是维护一份豁免清单每条豁免附上理由和责任人。误报允许豁免但必须是有人担责的显式决策而不是默认吞掉。规则集也要定期更新。AI 的写法在变漏洞模式也在变SAST 规则集半年不更新就跟不上节奏了。5. 第四根缰绳Agent自主操作时代权限边界要提前收紧代码生成只是 AI 安全的第一层现在越来越多团队开始让 AI Agent 直接干活——自己读文件、自己跑命令、自己改代码、甚至自己调用部署系统。这一层再不套缰绳前面做的所有防护都可能被绕过。5.1 从补全到执行Agent需要的不是信任而是围栏Copilot 这个级别的工具本质是给你建议最终操作权在人手上。但 AI Agent 不同它会根据目标自主决定执行哪些动作——修改文件、安装依赖、执行命令、调用 API。权限边界必须完全不同。我见过比较典型的翻车场景团队给 Agent 配置了一个拥有代码仓库写权限的 Token结果 Agent 在一次任务中试图执行git push --force直接在主干上覆盖了整段历史。代码本身没恶意但它的操作权限太宽了宽到可以执行破坏性命令。所以对于 Agent核心原则从信任但检查要变成默认拒绝按需放行。5.2 最小授权与默认拒绝Agent的权限设计原则给 Agent 授权的规矩类比一下就像给实习生发门禁卡只给他能完成工作所需的、最低限度的权限而不是整个办公楼的万能卡。落到工程实践上有几条硬要求Agent 使用的云凭证必须是独立于开发者的临时凭证用 STS 或 Workload Identity 下发有效期短、作用域窄绝不复用本地长期密钥。Agent 运行环境跟生产环境在网络上隔离默认策略是拒绝出网需要访问某个外部服务时逐一加白名单。Agent 执行敏感操作部署、删数据、改配置必须走审批流程也就是 human-in-the-loop。机器负责跑人负责按按钮。CI Token 使用后立即轮换不能做成永久有效的静态密钥。这里特别想说一下默认拒绝的价值。Agent 的行为空间越窄出事的半径就越小。哪怕它被恶意 prompt 注入了最多也只能在划定的小区域里折腾冲不破权限边界这堵墙。5.3 全程可观测每一行自动改动的来源都要能追溯权限做得再好如果没有日志出事时你还是两眼一抹黑。Agent 时代的可观测性要求比以前更高不仅是系统跑没跑的监控更是谁在什么时间、基于什么指令、做了什么操作的完整轨迹。我在实际项目里要求三条底线第一Agent 的所有终端操作必须记录 audit log包含命令内容、执行时间、操作对象第二Agent 触发的每一个 Git 提交都要在 commit message 里带上生成它的 prompt 编号或任务 ID第三所有由 Agent 创建的代码文件要在文件头部或 PR 描述里标注 AI-generated让后续维护者知道这段代码需要额外重点审查。有了这些标记你就具备反向追溯能力线上出了漏洞能从一行代码一路追到某次 Agent 执行记录搞清楚当时的生成上下文而不是靠人回忆。6. 把缰绳串起来一条可复制的AI代码安全流水线单条缰绳好套难的是让它们协同工作。最后这部分我把我团队现在实际跑通的一条 AI 代码安全流水线完整拆开你可以直接照着搭。6.1 从提示词到上线六道关卡这样串整个流水线我分成六道关卡每一道负责拦住一类问题前一道漏掉的由后一道兜底第一道输入隔离.cursorignore、代码库排除配置、密钥禁止进对话。既防止敏感信息泄漏给模型也减少 AI 因为看到太多上下文而产生的幻觉依赖。第二道生成侧约束AI 工具的企业策略统一开启隐私选项锁定安全基线写进团队规范。这道关卡管的是AI 允许看到什么、允许记住什么。第三道提交侧拦截pre-commit 钩子跑 gitleaks 和格式检查AI 生成的密钥、明显异常的文件都进不了 Git 历史。第四道CI 侧机械扫描SASTSemgrep/CodeQL扫代码漏洞osv-scanner/pip-audit 扫依赖 CVEsyft 生成 SBOM 留档。三道扫描任一不通过流水线直接 fail。第五道人工语义审查按前面那份 AI 代码安全 Review 清单逐项核对。机器只能找出已知的坏语义层面的这个业务逻辑该不该这么做必须由人来判断。第六道运行时防护Agent 走最小权限、临时凭据、默认拒绝网络上线后审计日志和监控盯着。这一道不是兜底漏洞而是兜底前面的关卡万一全漏了。6.2 一次真实事故复盘文件上传接口是怎么被AI写出漏洞的拿一个我复盘过的事故来说明整套流水线怎么发挥作用。需求很简单实现用户头像上传保存到 OSS返回 URL。AI 生成的接口大概逻辑是全对接收 multipart 文件、拼了一个uploads/加原始文件名的路径、直接 PUT 到 OSS、返回访问 URL。功能测试全过代码看起来一气呵成。漏洞在哪没有校验 Content-Type、没有限制文件大小、没有重命名文件——攻击者只要把原始文件名改成../../shell.jsp配合路径穿越和前端可控的 content-type就能把一个恶意文件上传到 OSS 桶再通过你的域名分发出去。这个事故里团队当时的情况是上下文没有隔离但问题不大因为代码里没有密钥pre-commit 也没拦住因为这不是密钥问题SAST 跑了一轮但规则集里没有覆盖到上传接口的参数校验模式人工 Review 全程在看业务逻辑没按安全清单走。四道关卡全漏了。后来我把规则集补上了上传文件类型白名单的检测Review 清单里加了文件上传专项项。再回头看这套流水线每一道单独都能拦住它SAST 能扫出未校验 Content-Type 的上传端点人工清单会强制检查重命名和大小限制。单一关卡不可靠但六道串联漏洞想漏过去的概率极低。6.3 我的几条笨规矩最后分享一些实际执行层面的感受。第一prompt 里永远带上安全要求虽然它不保证 AI 能做到但能给生成结果一个初始的安全锚点。我会在写实现登录接口这类需求时固定追加一句必须包含服务端输入校验、防暴力破解、错误信息不泄漏敏感内容。AI 会往这个方向生成后续审查的工作量小一半不止。第二任何 AI 生成的代码我不亲眼看过认证逻辑、输入校验、依赖来源这三件事就不允许合进主分支。这条规矩看起来很笨但它帮我拦下了不止一次线上事故。第三团队内部每个月抽一个下午专门拿之前 AI 生成的真实代码做一次安全复盘所有人一起过一遍哪些地方差点出事。这个动作比任何培训都有效——因为人对自己写过的代码记忆最深哪怕是 AI 代笔的。安全缰绳的意义不是拖慢 AI 写代码的速度而是让你在踩油门的时候不至于在下一个弯道直接冲出去。这套流水线搭下来之后我团队的 AI 辅助编程效率反而更高了——因为安全事故少了返工少了大家也终于敢放心地把更多活儿交给 AI 了。
返回列表