跳到主要内容

120 篇博文 含有标签「security」

查看所有标签

你的 Embedding 并不知晓外包人员已离职

· 阅读需 11 分钟
Tian Pan
Software Engineer

一名外包人员在上个季度结束了为期六个月的聘期。人力资源部门执行了离职清单:禁用 SSO、擦除笔记本电脑数据、移除 GitHub 席位、归档 Slack、撤销 Notion 访问权限。合规部门签字确认。六周后,一个内部 RAG 助手在回答问题时引用了该外包人员编写的一份机密战略文档——而引用的数据块在向量数据库的白名单中仍标记着该外包人员的用户 ID。事实来源(source-of-truth)的访问日志中没有任何读取记录,因为根本没有发生读取。检索来自一份从未被纳入离职流程的数据副本。

这是没人会画在架构图上的结构性问题。你的向量索引不仅仅是一个相似度搜索引擎。它是一个权限缓存——一个关于“谁能看到什么”的派生存储,冻结在你运行嵌入任务的那一刻——而且几乎没有人像失效其他内容那样去失效它。

无人书写的工具调用授权层

· 阅读需 10 分钟
Tian Pan
Software Engineer

你的 API 网关验证了用户身份。你的工具端点会检查用户是否有权删除该行。在这两次检查之间,存在一个并不存在的层:即决定模型在此次对话中是否被允许以这些特定参数请求 delete_user 的那一层。

在大多数智能体(agent)技术栈中,那一层就是系统提示词(system prompt)。它会说“小心执行破坏性操作”和“只删除用户明确要求你删除的记录”之类的话。这句话并不是访问控制。它只是对一个非确定性过程的礼貌请求,而评估该请求的组件,恰恰是攻击者试图操纵的那个。

你为单个智能体添加的工具,现在每个智能体都能用了

· 阅读需 11 分钟
Tian Pan
Software Engineer

六个月前,客户支持团队的人为他们的智能体连接了一个 send_email 工具。它奏效了。平台团队在共享工具注册表中注意到了它,在 PR 上点了个大拇指表情,然后就继续忙别的了。本周,一名安全工程师进行审计时发现,send_email 竟然出现在会议摘要智能体、数据质量机器人、一个没人正式负责的分析助手,以及一个自一月份以来就没动过的半成品原型中。这些智能体中没有一个需要发送电子邮件。而且,从来没有人审查过是否 应该 允许它们这么做。会议摘要智能体的 PRD 只有两句话长,其中根本没有出现 “外部通信” 这个词。

这是我审计过的每个共享工具注册表的默认状态。注册工具的行为——将 JSON 模式和处理器推送到中央目录中——被视为一种开发人员的便利,就像向共享库中添加实用程序函数一样。但一旦注册表被引入到每个智能体的提示词中,注册工具就不再仅仅是库变更。它是同时向公司内的每个智能体进行的部署,且完全没有审查每个智能体是否应该接收它。

权限提示是一个 UX Bug:当“人在回路”沦为“人工橡皮图章”

· 阅读需 10 分钟
Tian Pan
Software Engineer

观察一名开发者使用 Agentic 编程工具一小时,你会看到同一个动作重复四十次:弹窗出现,“允许 Agent 运行 git status 吗?”,手在眼睛读完之前就移到了批准按钮上。到第四十次提示时,提示内容根本没被阅读。它变成了一个用户学会全速通过的减速带。

这是“人机回环”(human-in-the-loop)的一种无声失败。架构图上仍然显示人类在把控每一个危险动作。审计日志仍然记录着对每个命令的明确批准。但人类已经停止了评估。他们变成了一个接入控制流的生物版 “yes” 函数 —— 虽然身在回路中,却不贡献任何判断。权限提示本应是一项安全控制,它却退化成了附带确认对话框的系统延迟。

Prompt Injection 是混淆代理问题,而非内容过滤问题

· 阅读需 12 分钟
Tian Pan
Software Engineer

在 Prompt Injection(提示词注入)违规事件发生后,最常见的调查结果通常是某种形式的“模型被骗了”。检索到的文档包含了隐藏指令,Agent(智能体)执行了这些指令,导致客户数据泄露。随后的修复方案几乎无一例外地是内容过滤器:扫描输入、对恶意指令进行分类,并在其到达模型之前将其剥离。部署过滤器,结案。

这个结论是错误的,而过滤器就像是一台无休止的“跑步机”。“模型被骗了”描述的是症状,而不是漏洞。漏洞在于,一个拥有实际权限的 Agent——如数据库令牌、发送邮件能力、文件系统写入权——接受了来自一个永远不该被允许指挥这些权限的来源的指令。这并不是一种新型漏洞,而是一个“混淆代理”(Confused Deputy)问题,操作系统在近 40 年前就已经对其进行了命名并基本解决了它。

如果你将 Prompt Injection 视为检测问题,你就是在参与一场与每一个能组织语言的攻击者之间的军备竞赛。如果你将其视为权限问题,你就可以复用数十年来行之有效的安全工程经验。

影子 AI:你的团队已经上线的 AI 智能体

· 阅读需 10 分钟
Tian Pan
Software Engineer

影子 IT 曾经意味着营销团队报销 SaaS 订阅,或者工程师私自创建 S3 存储桶。这很烦人,是采购方面的头疼问题,但大部分情况下是可以承受的。影子 AI 也是出于同样的本能——绕过缓慢的官方路径——只不过爆炸半径更大,且进入门槛几乎降至为零。

一名工程师可以在一个下午将 LLM API 调用接入生产工作流。一名支持主管可以在午饭前搭建一个无代码的分流智能体。一名数据分析师可以将一个季度的客户记录粘贴到聊天窗口中,以“快速总结一下”。这些都没有经过审查,没有出现在架构图中,而且你的治理计划无法保护一个它根本不知道存在的系统。

令人不安的是规模。2025 年 UpGuard 的一项调查发现,超过 80% 的员工——以及近 90% 的安全专业人员——在工作中使用未经批准的 AI 工具。你的安全团队在用,你的高管也在用。问题不在于你是否有影子 AI,而在于你是否能看到它。

你的工具描述是模型遵循的指令通道

· 阅读需 9 分钟
Tian Pan
Software Engineer

当安全团队审查一个新的工具集成时,他们会阅读代码。他们会检查函数的功能、它触及的内容、它需要的权限范围(scopes),以及它是否记录了敏感秘密。但他们几乎从不阅读那句决定模型是否调用该工具的句子——工具描述。那句话不仅仅是文档。它是模型视为权威的指令,而在大多数智能体堆栈中,没有人会去审计它。

工具描述是写给模型看的。模型利用它来决定工具何时相关、应该传递哪些参数,以及如何解释返回的结果。这使得描述成为了进入模型行为的一个控制通道。而当一个工具来自第三方注册表、一个你不运行的模型上下文协议(MCP)服务端,或者一个同事上周安装的插件时,这个控制通道的作者就是你从未同意信任的人。

这就是差距所在。输入净化(Input sanitization)检查用户输入的内容。代码审计(Code review)检查函数执行的内容。工具描述介于两者之间——它是表现得像输入的配置——它从这两个防护网中漏掉了。

AI 功能的自带密钥 (BYOK):没人预估过成本的销售驱动型架构重构

· 阅读需 11 分钟
Tian Pan
Software Engineer

你正在对接的采购团队最终会提出一个重置你架构的问题:“我们可以自带模型 API 密钥吗?”回答“可以”能赢得订单。但回答“可以”同时也意味着你的信任边界、成本边界和运营边界发生了转移 —— 而大多数产品团队只有在合同签署、第一个月的使用产生了一个没人知道如何回答的服务工单后,才会发现这一点。

BYOK 在公司内部推销时被视为一个开关。客户粘贴一个密钥,你的代码从保险库(Vault)读取它而不是从你自己的账户读取,然后推理流程照常进行。但这并不是一个开关。这是一场由销售驱动的架构重构,它会波及成本分摊、安全事件响应、可观测性、速率限制、模型版本锁定以及值班问责。那些在没有意识到这一点的情况下就交付产品的团队,最终会在一年后为了修复这些问题而重构整个平台层,而付费企业客户则在焦急等待。

少样本示例造成的租户泄露:当你的提示词库变成跨客户数据存储库

· 阅读需 13 分钟
Tian Pan
Software Engineer

打开一个日益成熟的 AI 产品的生产环境系统提示词(system prompt),向下滑过角色描述,你几乎总能看到一个标有 # Examples## Few-shot demonstrations 的部分。这些示例非常出色——它们很具体,具有领域针对性,且精准地匹配了上季度评估集(eval set)中表现不佳的失败模式。但在仔细观察后,你发现它们其实也是真实的客户数据。来自真实账户的真实工单 ID。从支持会话中原封不动摘录的措辞模式。某个租户使用的内部产品代码,而其他客户群从未听说过。

把这些示例放进去的团队并不是粗心大意。这些示例进入提示词的方式与好示例一贯进入提示词的方式相同:有人从生产环境的追踪(traces)中挖掘出模型处理不佳的案例,挑选出最干净的现成示例,将其粘贴到系统消息中,看着评估分数上升,然后发布。这条从生产环境追踪到系统提示词的流水线,是现代 LLM 工程中最可靠的提示词改进闭环。但这也是团队在不知不觉中构建的一个结构性跨租户数据泄露渠道,而系统提示词已悄然变成了一个数据处理协议(DPA)从未涵盖的多租户数据存储库。

你的微调语料库是代码库。别再通过存储桶交付了。

· 阅读需 12 分钟
Tian Pan
Software Engineer

在任何严肃的微调项目进入到第九个月时,你的训练语料库的作者数量可能已经超过了你的代码库。合成生成流水线编写了数百万个示例。供应商标注公司从你从未见过的劳动力那里贡献了 8 万行数据。一位工程师在上周二添加了 47 个示例,以修复他们在评估(eval)中发现的回归问题。一个抓取任务每天晚上将生产环境的追踪记录(traces)拉取到一个“补充”的 parquet 文件中。二月份有人扔进 S3 的一个 CSV 文件仍然在那里,仍然处于训练组合中,而编写该文件的人已经在三月份离职了。

现在看看你的应用程序代码仓库。每一行代码都可以追溯到具体的作者。每一次变更都经过了至少一名审核者的 PR。提交(Commits)是经过签名的。主分支(Main branch)是受保护的。合并需要第二个人参与。这里有审计日志。如果审计员询问 payment_processor.py 的第 47 行是谁写的,你可以在几秒钟内给出答案。

如果他们问产生模型 v2.3 的语料库中的第 47 个示例是谁写的,诚实的回答是“2024 年第二季度的 Mechanical Turk 批次,供应商未知,理由缺失。”你的微调语料库是比代码库权限更高的部署表面——它直接决定了生产环境中模型的行为——而你正在通过存储桶(bucket)发布它,却通过经过审查的 PR 发布代码。威胁模型被倒置了。

智能体临时目录:无人盘点的无主文件系统 PII 暴露面

· 阅读需 11 分钟
Tian Pan
Software Engineer

一位监管人员走进你的办公室,提出了安全团队反复演练过的那个问题:“请展示客户数据存放的每一个地方。” 你的数据团队拿出了清单。主数据库在上面。分析型数据仓库在上面。对象存储、队列、搜索索引、备份目的地——统统都在上面,附带着分类标签、保留政策、加密详情和负责人姓名。接着,房间里有人提到了 Agent 工作线程池,而清单上却对此只字未提。这个线程池已经运行了九个月。每个工作线程都有一个本地磁盘。这些线程上的 Agent 一直在解析 PDF、转录音频、下载邮件附件,并在工具调用之间缓存中间 JSON,而这一切从未停止过。却没有人将这些内容放入资产登记表。

这就是“临时目录问题”(scratch directory problem)。每一个长期运行的 Agent 工作线程都会积累一个临时文件系统,随着新工具的加入而有机增长——PDF 解析器提取的文本、Whisper 步骤转录的音频、Gmail 工具下载的附件、浏览器使用步骤的截图、为下一轮对话缓存的向量搜索片段、Agent 在两次工具调用之间生成的中间 JSON(以便第二次调用不必重新推导)。与数据库、队列和存储桶不同,这个表面没有保留政策,没有静态加密标准,没有 DLP 扫描器过滤,也没有出现在数据分类电子表格中。平台团队认为 “Agent 状态”指的是推理提供商的上下文窗口。SRE 团队认为 “Agent 状态”指的是持久化数据库。而工作线程的 /tmp/agent-workspace-${session_id}/ 目录则是客户数据的第三份副本,且处于无人管理的状态。

浏览器 Agent 会话泄漏:当单个 Profile 服务于多个租户时

· 阅读需 12 分钟
Tian Pan
Software Engineer

一个计算机使用型智能体(computer-use agent)在客户的 CRM 上完成了一项任务,工作线程池将浏览器返回到空闲环中,几百毫秒后下一个请求到达,仪表板导航成功——唯一的问题是,它是作为错误的用户登录成功的。前一个会话的 OAuth cookie 仍留在配置文件(profile)中。追踪记录显示 navigation succeeded(导航成功)、screenshot captured(截图已捕获)、action performed(操作已执行)。运行日志中没有任何内容表明,智能体正在以一个从未授权过它的用户身份进行操作。

这是浏览器智能体从其构建所用的库中悄然继承的一类故障。无头浏览器(headless browser)框架被设计为每个配置文件仅供一个用户使用,因为这是浏览器三十年来的工作方式。当工作池为了摊销全新的 Chromium 实例长达八秒的冷启动时间而重用配置文件时,这种“单用户”假设就破裂了,而且这种破裂对于团队通常信任的每一层遥测数据来说都是不可见的。