文章揭示AI生成代码常见安全风险,如API密钥泄露导致数千美元账单,并给出防护建议。
把你的第一款应用发布出去感觉超棒。你的想法终于可以让全世界看到了。你发了链接,有人注册了,一切都顺风顺水——直到你收到一张 4000 美元的 OpenAI 使用额度账单,而那些 API 调用根本不是你做的。
不幸的是,这是凭感觉编程项目出问题的最常见方式之一。有人查找新应用中暴露的密钥,用它们来运行昂贵的 AI 模型,然后在你睡觉的时候累积出一笔巨额账单。
在这里,我将引导你如何避免这种情况——以及其他常见的问题——而无需成为一名安全工程师。我会深入探讨最常见的漏洞,并给你一些可以安装到你喜欢的 AI 编码工具中的 AI 智能体技能,用于扫描和修复漏洞。我希望你离开时能带着意识和词汇来与你的 AI 智能体交流并解决安全问题。
为什么凭感觉编程安全很重要
凭感觉编程安全 AI 智能体技能
凭感觉编程安全 AI 智能体技能
如何确保你的凭感觉编程应用是安全的
如何确保你的凭感觉编程应用是安全的
它带来的是安全的感觉
它带来的是安全的感觉
那句"一个周末就能构建一个应用"的营销文案后面还应该加上一句警告:"一个周末也能部署安全漏洞。" Veracode 2025 年的报告发现,45% 的 AI 生成代码包含安全缺陷。
当你最终部署那段代码时,它可能会公开暴露数据:2026 年 5 月,研究人员扫描了超过 5000 个凭感觉编程的应用,发现 40% 暴露了敏感数据。其中包括医疗信息、企业演示文稿、客户详情、财务记录——甚至还有用户与聊天机器人工具之间的完整对话日志。
这些统计数据对你实际意味着的是,当你在凭感觉编程一个应用时,你面临以下几类关键风险:
数据泄露。恶意行为者可以读取、修改和窃取你数据库中的数据(你和你用户的数据)。
数据泄露。恶意行为者可以读取、修改和窃取你数据库中的数据(你和你用户的数据)。
应用接管。攻击者可以获得管理员访问权限,控制你的应用或网站,用它来传播恶意软件或发起勒索攻击(扣押你的数据并以此换取金钱)。
应用接管。攻击者可以获得管理员访问权限,控制你的应用或网站,用它来传播恶意软件或发起勒索攻击(扣押你的数据并以此换取金钱)。
API 密钥被盗。任何拿到这些密钥的人都可以消费你的额度,特别是在 AI 模型和云计算平台上。
API 密钥被盗。任何拿到这些密钥的人都可以消费你的额度,特别是在 AI 模型和云计算平台上。
声誉损害。如果你是为公司或客户构建的,一次事件可能导致丢掉工作或合作关系;当为客户构建时,可能导致用户在阅读网上评论后不再注册。
声誉损害。如果你是为公司或客户构建的,一次事件可能导致丢掉工作或合作关系;当为客户构建时,可能导致用户在阅读网上评论后不再注册。
我已经为我的 Claude Code 环境生成并调整了 AI 智能体技能,以确保我了解项目中存在的漏洞。如果你想要快速上手,去这个 GitHub 仓库安装这些技能。
虽然我已经尽我所能让它们捕获尽可能多的问题,但它们绝不是完全无懈可击的。我提供它们时不附带任何形式的保证。请随着时间推移调整这些技能,以覆盖你项目的安全需求和新发现的威胁。
不幸的是,没有办法让一个应用 100% 安全。但当你开始填补安全漏洞时,你就减少了你基础设施的攻击面。攻击者需要尝试访问的门会变少,而那些确实存在的门也更难被攻破。
永远不要假设 AI 生成的代码开箱即安全。每次你发送提示词时,它总是会优先遵循你的指令并给你一个可用的输出。
第一步:在你的规则文件中添加安全指令。用一套安全原则更新你的 CLAUDE.md 或 AGENTS.md,这些原则会引导 AI 智能体的决策默认倾向于更安全的实现。包括对你正在构建什么以及为谁构建的描述:放在内部网络中的应用与放在开放互联网上的应用是不同的。
在你完成一个新功能或一大批修复之后,你应该让你的应用经历一次安全审查,以捕获尽可能多的漏洞。
构建一个 AI 智能体技能来自动化这个过程——或者安装我在这里的技能。它应该处理两个主要任务:
威胁建模评估。这旨在了解可以对你的基础设施使用的攻击类型。它分析你正在使用的服务,它们如何连接,以及每个组件中存在哪些权限。这本质上是一种自上而下的检查,看看你的应用是否为安全而设计。
威胁建模评估。这旨在了解可以对你的基础设施使用的攻击类型。它分析你正在使用的服务,它们如何连接,以及每个组件中存在哪些权限。这本质上是一种自上而下的检查,看看你的应用是否为安全而设计。
代码扫描常见的危险或易受攻击的模式。这检查代码是否包含可能被轻易利用的部分。这是自下而上的检查,控制代码质量。
代码扫描常见的危险或易受攻击的模式。这检查代码是否包含可能被轻易利用的部分。这是自下而上的检查,控制代码质量。
在用 AI 找到并修复错误之后,使用代码扫描工具来寻找导致漏洞的模式。你可以将报告反馈给 AI 智能体进行修复。以下是一个列表:
Semgrep。它使用 30 多种语言的 2000 多条开源规则扫描你的源代码中的危险模式(SQL 注入、硬编码密钥、不安全的输入处理)。从 CLI 或托管检查免费运行,每条发现都带有一个你可以交给 AI 智能体的解释。
Semgrep。它使用 30 多种语言的 2000 多条开源规则扫描你的源代码中的危险模式(SQL 注入、硬编码密钥、不安全的输入处理)。从 CLI 或托管检查免费运行,每条发现都带有一个你可以交给 AI 智能体的解释。
Snyk Code。这是一个静态分析工具,有免费层级(每月 100 次扫描),可以实时标记代码漏洞,并在每个结果中包含修复指导。
Snyk Code。这是一个静态分析工具,有免费层级(每月 100 次扫描),可以实时标记代码漏洞,并在每个结果中包含修复指导。
GitHub CodeQL。这个内置于 GitHub;开启代码扫描,它会分析每次推送的安全问题。对公共仓库免费。
GitHub CodeQL。这个内置于 GitHub;开启代码扫描,它会分析每次推送的安全问题。对公共仓库免费。
最后,要防范依赖幻觉。依赖是一个简化应用开发的代码集合:例如,OpenAI SDK 让你无需编写自定义集成,用一个关键字替换多行代码。AI 编码智能体有时会幻觉出依赖名称,将它们添加到你的代码中,即使它们根本不存在。
攻击者已经开始利用这些幻觉,做一种叫做 slopsquatting 的事情:他们注册这个幻觉的依赖,在其中添加恶意代码,这样你的应用会在你不知情的情况下运行它。
请让你的 AI 智能体列出项目中每个依赖及其选择原因。要检查一个名称,自己去 npmjs.com(或 Python 的 pypi.org)搜索,并 Google 这个名称加上"scam"或"is it safe"等关键词。
在注册页面上,任何只有几十次下载、非常新,或者停在 1.0.0 版本且没有历史的都是红旗。寻找大下载量和链接的代码仓库(通常是 GitHub)且看起来活跃的——如果缺少任何一个,都不要安装。还要逐字符读名称:攻击者会注册看起来很像的仿冒品,比如用 dateutils 冒充 dateutil,或者用连字符换下划线。
要自动化这个流程,安装 Socket(一个 GitHub 应用)来为你运行这些检查;对小项目免费。
你的数据库是你数据宝库。它保存着可能暴露你或你用户的敏感信息。如果攻击者能够读取、下载或修改你的数据库,这就是一次数据泄露,是应用接管的入口,也是用你的应用攻击用户设备的途径。
为 PostgreSQL 类型数据库(如 Supabase)配置行级安全(RLS)可以覆盖大部分风险。配置完成后,数据库只会根据预设规则返回每个用户有权访问的数据。如果攻击者试图通过你的应用查询超出权限范围的数据,数据库不会返回所有数据,而只会返回与该用户权限对应的数据集。
大多数数据库平台会在 RLS 未启用时显示严重警告通知,所以在仪表板上很容易看到配置是否正确。但为了确保万无一失,请检查以下事项:
RLS 已开启。这是阻止数据访问的执行引擎。
策略已就位。这是一份指令列表,规定每种数据类型每个用户可以创建、读取、更新或删除(CRUD)的操作。
如果策略已配置但 RLS 关闭,你的数据将完全暴露。启用了 RLS但没有策略的数据库不会向应用返回任何数据——本质上是拒绝所有访问的行为。
幸运的是,大多数数据库 MCP 服务器都支持通过对话轻松激活、停用和调整策略。每当你做出重要更改时,请检查数据库的应用界面,确保一切都是按计划实施的。
注意:如果你使用的是 NoSQL 替代方案(如 Firestore),请配置其安全规则。这些规则在查询时生效,即你的应用向数据库发起查询时。如果查询请求的信息超出允许范围,Firestore 会拒绝整个查询并返回空数据。在排查问题时请记住这一点,因为严格的权限配置可能会导致应用中的某些列表无法加载。
大多数应用依赖第三方服务,如用于支付的 Stripe、用于事务邮件的 SendGrid 以及用于 AI 功能的 OpenAI。这些服务都会为你提供一个 API 密钥,用于在平台上识别你的身份并帮助计费。
密钥相当于打开酒店每个房间的万能钥匙。务必始终保护好你的密钥。
永远不要直接粘贴到代码行中。
永远不要在截图、视频中包含它们,也不要在直播构建时让其出现在屏幕上。
不要与任何不需要的人分享。
永远不要将其作为提示的一部分发送给任何 AI 服务。
开发应用时,你的密钥应存放在 .env 文件中。代码应被修改为指向该文件中的密钥,这样密钥只会在代码运行时被读取。确保这个文件已列入 .gitignore,这样它就永远不会被提交到 GitHub:公共仓库中一个被提交的 .env 文件是大量密钥泄露的途径。
然后,当你将应用部署到托管平台时,需要将这些密钥添加为环境变量,并让代码指向它们而不是本地文件。请参阅你的平台说明了解如何操作:
Cloudflare Workers & Pages
某些服务还提供可发布密钥。顾名思义,这些密钥可以被发布并在应用前端可见,这样你的应用可以指向你拥有的资源。安全层在使用可发布密钥连接服务后才强制执行。这些就像是访客钥匙卡,只能打开你允许访问的区域。
对于 Supabase,这个密钥被称为 anon 密钥。安全层是前面探讨过的 RLS:可发布密钥让你的应用可以向数据库发起查询,但决定返回什么内容(如果有的话)的是 RLS。
其他提供可发布密钥的服务包括:支付(如 PayPal)、身份认证服务(如 Clerk、Auth0)、优化工具(如 Algolia)、错误追踪(如 Sentry)或媒体托管(如 Cloudinary)。非常重要:这些服务可能也会随可发布密钥一起提供密钥。设置之前请务必区分哪个是哪个。
可发布密钥在本地开发时也应存放在 .env 文件中。尽管它们本来就是设计为暴露的,但这有助于保持组织有序,并且在你想指向另一个项目时更容易轮换。部署时,它们也将存放在托管平台的环境变量中。
不要心存侥幸,而要假设你的密钥已经泄露。现在就做以下事情:
让你的智能体设置一个 .env 文件,并用指向该文件的引用替换所有可见的密钥。
前往每个受影响的 API 服务,重废/删除/轮换旧密钥。
创建一个新的 API 密钥,并将其粘贴到 .env 文件中的相应位置。
将代码部署到生产环境,并使用你的密钥更新托管平台的环境变量。
记住:可发布密钥本来就是设计为公开的。不需要轮换它们。
如果你发现 API 平台的支出和使用量增加,请首先检查:这是否与新付费用户相关?如果是,你的应用可能正在病毒式传播,而不是受到攻击——恭喜你的营销策略。
如果你真的受到攻击了,请保持冷静。严格按照以下步骤操作。
立刻:遏制损失。
登录受影响的 API 服务。
点击撤销/删除/轮换。
被盗的密钥现在已无用。
下一步:告知用户受影响的功能将不可用。主动这样做可以保护你的声誉,并防止大量客服消息涌入。
除非用户数据被访问和窃取,否则你不必说正受到攻击。在这种情况下,根据你和你用户所在的地区,你可能在法律上有义务将其披露为数据泄露(欧盟在这方面有严格规定)。如果没有用户数据被触及,不要将其定性为攻击;修复它然后继续。
尽快:修复代码。
告诉你的智能体发生了什么。哪个密钥泄露了,造成了什么损害,以及从你的平台获得的任何其他支持信息。
让智能体修复它发现的任何漏洞。导致这种情况的两个最常见的安全问题是:密钥暴露在前端,或使用计量功能时访问控制/速率限制不当(我将在下一节深入探讨这两个问题)。
返回 API 服务平台,生成一个新密钥,并在 .env 文件中替换旧的。
测试你的应用,看是否一切正常运行。
将代码部署到你的托管服务。
将新密钥添加到托管平台的环境变量中。
接下来的几周内:监控你的 API 服务仪表板。在接下来的几周内密切关注提供商的用量仪表板和账单异常。对于按用量计费的服务,探索设置预算警报或消费上限的方法。(但请记住,设置硬性上限可能会在你应用病毒式传播时造成伤害。)
你的数据库现在已被锁定,你的密钥也是安全的。是时候关注访问控制了。访问控制也称为授权,它控制哪些页面加载、哪些按钮生效、以及哪些 API 调用实际运行。
以下是通常容易出现漏洞的地方:
已注销访客的行为
创建账户和登录
特权操作的服务器端检查
转义用户内容
暴露过多数据
额外加分项:阻止机器人、暴力破解和垃圾信息
对于已注销用户,确保你的应用只展示公开页面和公开数据。即使有人猜到了只有登录用户才能访问的直接链接(如 /profile 或 /admin),你的应用也不应允许他们查看或操作任何内容。这就是你想要的默认行为:你的应用不信任任何没有访问凭证的人。
当有人创建账户时,你需要创建他们的记录并分配所需的权限。为简化这一步的安全流程,可以使用 Supabase 或 Firebase 这样的平台来处理。
注册过程也是分配用户权限的地方。例如,如果有人作为免费用户创建账户,你要附加一个表示其权限级别的数据字段。付费用户的流程相同,无论你在应用中实现了多少种定价方案。
每次用户想做需要权限的事情(如登录或订阅特定定价方案)时,都要始终针对自己的数据进行检查,而不要在用户设备的前端进行检查。恶意用户可以编辑其设备上的本地代码并修改数据,比如修改其层级的名称,从而在不付费的情况下访问付费功能。
要求你的 AI 智能体在页面、按钮或视觉元素(即使它们是隐藏的)上添加服务端检查,这些元素会根据用户权限而变化。
输入字段(如文本框)需要规则来阻止无意义的数据进入。年龄字段应该只接受数字;截止日期字段应该只接受日期输入。你的数据库本身就会拒绝不匹配的数据类型,但在前端添加输入验证是另一层保护。
这也是在用户界面中添加说明性文案的好时机,向用户解释对他们的期望——这是用户体验的最佳实践。
当用户可以看到彼此的内容时——例如社交媒体应用——你必须确保这些内容在任何设备上都不会被视为可运行的代码。如果做不到这一点,攻击者就可以将他们的名字设置为一个代码片段,从任何渲染该数据的计算机中提取信息。
告诉你的 AI 智能体将所有用户提交的内容渲染为纯文本;如果需要富文本格式,要让它经过一个消毒器。
当用户在你的应用中导航到新页面时,他们的浏览器会请求显示该页面所需的数据,这些数据是你在代码中定义的。问题出在它请求了不必要或敏感的数据上。
假设你有一个个人资料页面,向用户展示他们的个人信息并允许他们编辑。如果页面只显示姓名和电子邮件,你的应用应该只请求这两个字段,即使你的用户记录中还包含内部备注、用户地址或账户中的项目数量。
在这里采取防御姿态可以保护用户数据并使你的应用免受利用。
处理文件的应用需要严格的方式来接收、存储和将文件返还给用户。例如,如果恶意用户上传的是脚本而不是 PDF 文档,它就可以在查看者的机器上运行。更糟糕的是,它可以在你的服务器上运行并将控制权转移给攻击者。
使用专用存储服务,如 Supabase Storage、Amazon S3 或 Cloudinary。这让你从第一天起就拥有更少的复杂性和更好的安全性。

限制文件类型。在前端,只接受特性所需的 .pdf 或 .jpg(这又是输入验证)。在后端,检查文件的魔术字节来确认它确实是那种类型——攻击者可以轻松地将有害文件重命名为 photo.jpg。

上面所有内容都是关于谁能访问什么。这一部分是关于量的:即当有人每分钟发送相同请求 10,000 次时会发生什么。他们这样做可能有三个原因之一:
试图入侵。例如,他们可能正在用尽可能多的邮箱/密码组合来暴力破解你的登录页面。

试图让你超支。也许他们正在猛烈请求你需要付费的端点,比如付费 API。这与窃取你的 API 密钥不同:他们是在滥用你构建的合法功能,而不是自由使用你的密钥。

试图淹没你。这意味着用垃圾数据填充你的数据库,让你达到配额而无法管理你的应用。

速率限制可以解决这个问题:规定某人使用某个功能的频率和持续时间。例如,Google Sheets API 将每个用户的读取请求限制为每分钟 60 次;第 61 次会返回 "429: Too many requests",直到该分钟重置。
大多数身份验证平台(包括 Supabase)已经对登录和密码重置进行了速率限制。对于你自己的端点或 AI 特性,要求你的 AI 智能体为它们添加速率限制层。
记住,速率限制只会减缓单一来源,但无法阻止多个僵尸网络。为此,在你受到猛烈攻击的页面或功能上添加 CAPTCHA 或 Cloudflare Turnstile。这是在正确位置添加几行代码,而不是自定义逻辑。
将敏感逻辑放在用户设备之外
当你打开一个 URL 时,你的设备会下载显示页面所需的大部分代码和资源,这些是开发者预设的。一旦代码到了你的设备上,你就可以检查和修改代码。看一下这篇 inspect element 指南,看看选择页面上任何内容有多么容易。