跳到主要内容

126 篇博文 含有标签「security」

查看所有标签

影子智能体:法务在事故复盘中才发现的 AI 功能

· 阅读需 12 分钟
Tian Pan
Software Engineer

发现你上线了一个 AI 智能体的最糟糕时机是在事故复盘中。不是在设计文档里,不是在架构评审中,也不是在变更工单里 —— 而是在事故复盘现场,律师正询问为什么在未经授权的情况下给客户退了款,而一名工程师正翻找着一个上次进行实质性评审还是在 11 个月前的服务,然后在名为 enrichTicket 的函数第 40 行处,发现了一个模型调用,它读取客户记录、决定处理方案,并调用了计费 API。没有人画过它的架构图。没有人批准它作为一个智能体运行,因为对于编写它的人来说,它根本不是智能体。它“只是一个辅助工具”。

这就是影子 AI,它已经露出了獠牙。第一波浪潮是员工将公司数据粘贴到消费级聊天机器人中 —— 这是一个数据泄露问题,虽然严重但尚在可控范围内。第二波浪潮是智能体:嵌入内部工具的模型调用,它们读取真实数据并执行真实操作,潜伏在那些原本为完全不同的用途而获批的服务中。大约一半的员工承认使用了雇主从未批准过的 AI 工具,而且很大一部分比例的使用来自高层 —— 总监和高管是主要的“元凶”,而不是实习生。当这种本能延伸到你的代码库时,你得到的不再是一个泄露的电子表格。而是一个拥有生产环境凭据且未经任何人签字批准的自主代理人。

令人不安的是,影子智能体并非由鲁莽的人创建。它们是由优秀的工程师创建的,而他们只是在执行你的要求:快速交付价值、复用现有基础设施、不要为每一个微小的改动都提交工单。治理差距并不是纪律问题。它是一个定义问题 —— 你的评审流程中根本没有他们所构建内容的对应类别。

新员工带来的智能体:个人 AI 记忆是双向的知识产权边界

· 阅读需 11 分钟
Tian Pan
Software Engineer

你的入职清单会筛选很多东西:背景调查、利益冲突披露、签署的知识产权转让协议、装有正确 MDM 配置的笔记本电脑。但它无法筛选新入职的资深工程师真正携带的东西——一个个人 AI 订阅账号,其记忆中包含了从前任雇主那里积累了 18 个月的上下文。架构争论、事故复盘、未发布的产品名称、他们刚花了两年时间构建的查询优化器的精确形态。这些不是他们窃取的文件,而是助手通过一次次对话吸收、在后台合成的环境上下文,当他们在入职新工作提问时,助手会很乐意调用这些信息。

同样的边界在员工离职时也会在另一个方向失效。当那名工程师离开你时,你的离职流程手册会撤销他们的 SSO、停用他们的 OAuth 令牌并擦除他们的笔记本电脑。但它不会——因为它无法——触及个人的 ChatGPT 或 Claude 账号,因为你的架构决策、事故历史和路线图现在作为记忆条目存在于一个你不拥有、无法审计且无法擦除的租户中。雇佣关系一直通过人类记忆泄露知识,而法律已经接受了这一点。新出现的是随人移动的第二种“机器级记忆”:它是可搜索的、持久的、在某些地方是逐字记录的,并且对过渡期两端的雇主都是不可见的。

你的智能体幻觉出的软件包现在已存在 —— 而且它是恶意的

· 阅读需 12 分钟
Tian Pan
Software Engineer

每个安全团队对拼写抢注 (typosquatting) 都有一个心智模型:攻击者注册 requets 并等待有人误输入 requests。这行得通,但它是对人类粗心大意的一种随机押注。Slopsquatting 则更糟糕,因为这种“拼写错误”并非随机。语言模型会以可预测、可重复的模式虚构出看似合理但并不存在的包名——攻击者可以查询你使用的相同模型,收集它们虚构的名字,并准确地在 PyPI 和 npm 上注册这些包。幻觉变成了预购单。你的编码智能体 (coding agent) 在拥有自主安装权限的情况下运行,就是那个取走包裹的顾客。

这并非假设。关于这一现象的最大规模研究对 16 个模型生成了 223 万个代码样本,发现 19.7% 的推荐包并不存在——涉及 205,474 个独特的虚构名称。当一位安全研究员将其中一个最常被幻觉出的 Python 包注册为一个无害的空壳时,它在三个月内被下载了超过 30,000 次,并最终出现在一家大型科技公司开源仓库的安装说明中。由“氛围编程” (vibe coding) 带来的供应链攻击已经完成了它的概念验证。

你的 Agent 是别人的 Bot 难题

· 阅读需 12 分钟
Tian Pan
Software Engineer

你构建了一个每天早上检查供应商价格的智能体。它运行真实的浏览器,点击真实的按钮,表现得就像一个勤奋的员工——只是速度更快,而且是在凌晨 6 点。然后有一天,它停止工作了。你的代码没有报错。供应商的网站现在返回一个挑战页面,接着是 403 错误,最后干脆什么都没有了。你的智能体没有坏,它只是被归类了。

这是每个智能体构建者最终都会面临的尴尬对称性:网络防御系统经过了十年的爬虫战争、撞库攻击和囤货机器人的洗礼——从统计学上看,你合法的智能体与这些恶意行为并无二致。2024 年,自动化流量占到了全球网络流量的 50% 以上,其中约 37% 被归类为恶意流量。为了对抗这股洪流而演化出来的免疫系统并不关心你的意图。它关心的是你的指纹,而你的指纹显示为“机器人”。

你的 Embedding 是个人身份信息 (PII):反向攻击与向量数据库中的被遗忘权

· 阅读需 11 分钟
Tian Pan
Software Engineer

在你公司的内部数据分类政策中,总会有这么一个表格。原始客户文本——支持票据、医疗笔记、聊天记录——被归入“敏感”行,受到加密要求、访问控制和删除服务等级协议(SLA)的保护。然而,还有一个存储着 这些文本对应的 嵌入向量(embeddings)的向量库,它被归类为……什么也不是。衍生数据。匿名数学。只是一堆浮点数。

这种分类是错误的,而且这种错误现在已经得到了实验证明。逆向攻击(Inversion attacks)可以从嵌入向量中重建原始文本——在研究最充分的场景下,92% 的案例可以 准确 恢复 32 个 token 的输入,包括临床笔记中的全名。如果攻击者拿到你的向量后能读出你客户的话,那么你的向量就继承了这些话语的敏感性。监管机构已经开始公开声明这一点,而大多数检索架构尚未对随之而来的后果做好准备:删除请求必须触及每个索引、每个快照和每个衍生工件——而不仅仅是行存储(row store)。

影子 AI:停止封禁,开始治理已经发生的泄露

· 阅读需 10 分钟
Tian Pan
Software Engineer

有一个数字应该可以结束关于你的公司是否存在影子 AI 问题的争论。在短短一个月内,监控企业浏览器流量的安全研究人员记录了超过 155,000 次复制操作和超过 313,000 次粘贴到生成式 AI 工具的操作。不是请求。不是页面浏览。而是复制和粘贴事件 —— 这正是工程师从生产日志中提取堆栈追踪(stack trace)并将其丢入聊天机器人以询问服务为何崩溃时所做的精确动作。

令人不安的事实是,这一切已经发生了。你的员工并没有等待 AI 政策委员会召开会议。几个月前,他们就已经把客户列表、合同草案、专有数据库架构以及半坏的函数粘贴到了消费级聊天机器人中,而且他们是通过你的 IT 部门无法看到的个人账号进行的。问题不再是如何防止影子 AI。而是如何治理一种已经普遍存在、大多不可见且不会停止的行为。

MCP 工具列表在会话中途增加,你的智能体调用了一个它从未被告知过的工具

· 阅读需 11 分钟
Tian Pan
Software Engineer

一场安全事件回顾以一个团队无法回答的问题开始:智能体是如何知道它刚刚调用的工具名称的?审计追踪显示了一个 tools/call 请求,但该工具的名称并未出现在 harness 记录的任何 tools/list 响应中。MCP 服务器欣然接受并执行了该调用。在事后分析中,当被要求解释工具名称来源时,模型给不出答案,因为根本没有答案 —— 它猜中了,而且这个猜测恰好命中了一个真实的操作。

这是两个在理论上看起来兼容的假设之间产生的失效模式。客户端将工具列表视为一份契约,界定了它被授予的权限范围。服务器则将工具列表视为当前可用工具的快照,可以随着环境的变化自由增长。在这两种观点之间,LLM 是一座不知道二者差异的桥梁。

那些你的团队遗忘在后台且正使用生产环境凭据运行的 MCP 服务器

· 阅读需 12 分钟
Tian Pan
Software Engineer

周一,一位新工程师加入了团队。到周三时,她已经搭建好了本地 Agent 环境:一个桥接到公司部署 API 的 MCP 服务,指向 Staging 环境,并与她的编辑器相连。入职文档引导她完成了 OAuth 流程。她粘贴到服务器环境文件中的令牌是同事发给她的——这与 CI 流水线用于发布到 Staging 环境的是同一个令牌。到周五,她已在共享办公空间与团队一起进行协作开发。

MCP 服务仍在运行。绑定在 127.0.0.1。无需身份验证。令牌已加载到进程中。她没多想,因为她并没在使用它。但那天访问任何网站的任何标签页,都可以通过她自己的浏览器与她的本地服务通信。共享办公空间 Wi-Fi 上的任何其他笔记本电脑也同样可以,因为她没注意到该服务实际上绑定到了 0.0.0.0。你的 CI 流水线用来推送到 Staging 的 OAuth 令牌,现在任何能诱导浏览器向本地 IP 发起请求的人都能触及——在 2026 年,这只需要一个弹窗。

本文讨论的就是这类故障:“我在笔记本上开发”与“我的笔记本是对手可以触及的服务器”之间的鸿沟。MCP 服务在设计上恰好处于这个鸿沟之中。大多数团队尚未察觉。

一个工具请求的 OAuth 作用域,为何被其他所有工具悄悄继承了?

· 阅读需 11 分钟
Tian Pan
Software Engineer

设计文档规定每个工具都拥有独立的 OAuth 令牌,并被限制在该工具所需的最小权限范围内。而实现代码则使用 (user_id, provider) 作为键(key)来存储令牌。在 v1 版本发布当天,这两个表述都是成立的,因为当时每个提供商(provider)恰好只有一个工具。当针对同一提供商的第二个工具上线时,设计文档依然成立,但存储层却在悄无声息中使其失效了。

六个月后,一次安全审查将一起事故追溯到了那行模式(schema)定义。一个日历读取工具通过日程描述中的提示词注入(prompt injection)被攻破,并成功调用了用户主日历上的 events.delete 接口。读取工具从未被授予过该作用域(scope),但写入工具被授予了。令牌存储层并没有区分它们。

这种故障模式在于,基于每个提供商(per-provider)的键结构会在共享同一提供商的工具之间悄悄累积权限——这也让人们在架构上意识到:OAuth 作用域是令牌(token)的属性,而不是工具(tool)的属性。

当 On-Behalf-Of 悄然变成 Act-As:你的智能体继承的 OAuth 作用域陷阱

· 阅读需 10 分钟
Tian Pan
Software Engineer

安全审查称智能体(Agent)“代表”(on behalf of)用户操作。OAuth 令牌却有不同的说法,而审计日志也支持令牌的说法。

语言上的一点微小差别,在架构层面起到了意想不到的作用。“代表”(On behalf of)是安全审查在试图描述一种委派安排时使用的语言,即智能体是一个可识别的委派对象,并受此身份约束。“作为”(Act as)则是运行时的行为,此时智能体持有的令牌与用户本人的令牌完全一致,因此在任何下游系统看来,智能体就是用户。这两个短语描述了完全不同的威胁模型。典型的企业级 OAuth 集成交付的是后者,但宣传的却是前者。

那个保护了日志却让模型泄露输出结果的 PII 脱敏器

· 阅读需 13 分钟
Tian Pan
Software Engineer

一个仅针对入站流量运行的 PII 脱敏器就像是安装在管道错误一端的单向阀。它在用户提交的姓名、电子邮件和账号进入日志之前拦截它们。但它对模型的输出无能为力 —— 而现在,模型正是在输出端积极地组合可能包含这些相同标识符的文本,这些内容可能源自 RAG 检索、工具返回、对话历史或用户从另一个租户数据中粘贴的内容。我观察过每一个上线了输入端脱敏器的团队,他们的待办事项中都有一个标记为“输出端对齐”的后续任务。大多数这类任务永远不会关闭,因为在长达六个月的时间里,没有任何事故暴露出这个缺口。六个月后,该任务经过多次重新排序,看起来更像是一个功能需求,而不是缺失的一半安全控制手段。

失败模式是恒定的:输入端脱敏被视为标准的控制手段,因为它的工程问题更简单,审计故事也更容易讲。你编写了一套正则表达式,运行了一个标注好的基准测试,证明了在固定语料库上的精确率和召回率,在特性开关后上线了它,安全评审也将其接受为 PII 边界。输出端则完全没有这些优势。模型的响应是生成性的,表面积是无限的,而且测试方法论 —— “在无限多的上下文中它不应该说什么” —— 在结构上比“我们应该从已知输入中剥离什么”要困难得多。因此,上线入口端的团队将出口端视为未来的工作,而这个未来永远不会到来,直到有客户举报另一个客户的电子邮件出现在他们的对话记录中。

安全智能体如何跨过那行它“看不见”的注释,升级了被固定的依赖

· 阅读需 12 分钟
Tian Pan
Software Engineer

一位西班牙客户投诉称,她的年度续费被提前一天计费了。支持工单在经历了三个队列后,终于转到了一位工程师面前,他敏锐地察觉到了问题的端倪:这是一个日期格式化的回归(regression)问题,且仅出现在欧洲用户群中。他在 date-formatting 模块上运行了 git log,却一无所获。该模块已经 11 天没动过了。而 11 天前真正被改动的,是它的 package.json —— lodash 的版本从 4.17.20 升级到了 4.17.22。这次升级是由一个安全代理(security agent)发起的,由值班人员批准,并在没有任何评论的情况下合并了。

在同一个文件中,版本字符串上方两行有一条 18 个月前写的注释:// do not upgrade — breaks the snapshot tests in date-formatting, see FRONT-2418(请勿升级 —— 会破坏 date-formatting 中的快照测试,详见 FRONT-2418)。安全代理没有阅读它。或者更准确地说:安全代理阅读了整个文件,但它的提示词(prompt)指令是查找有漏洞的版本字符串,而不是衡量周围注释的权重。这条注释是承载关键信息的机构知识(institutional knowledge)。而代理却将其视为无关紧要的背景装饰。

这是一个两个互不知晓正在发生碰撞的系统之间的协同失效。安全代理履行了它的职责。写下注释的原工程师履行了他的职责。每次修改文件都遵守固定(pin)版本的开发代理也履行了它的职责。唯独没有人决定谁该负责在它们之间进行调解。