AI 编码智能体通过简化任务和推动测试驱动的自动化开发,使开发者能够更高效地工作。然而,它们也引入了一个常被忽视的重要攻击面:即在命令行中运行工具时,拥有与用户相同的权限和授权,使其成为计算机使用代理,从而带来相应的安全风险。
这些工具面临的主要威胁是间接提示注入,即驱动模型的 LLM 所获取的部分内容由对手通过向量提供,例如恶意仓库或拉取请求、含有提示注入的 git 历史记录、.cursorrules、包含提示注入或恶意 MCP 响应的 CLAUDE/AGENT.md 文件。此类针对 LLM 的恶意指令可能导致模型执行受攻击者操控的操作,进而引发不良后果。<!–
手动批准智能体执行的操作是管理此风险的常见方式,但这也会给开发者带来持续的操作负担,需反复返回应用以审查并批准操作,进而可能催生用户习惯性行为——即未经充分审查便直接批准潜在风险操作。代理式系统安全的一项关键要求,是在人工干预与自动化之间取得平衡。以下控制措施被NVIDIA AI Red 团队视为必要或强烈建议,但其具体实施应结合您的实际用例及组织的风险承受能力。
根据 NVIDIA AI 红队 的经验,以下 强制性 控制措施可有效缓解由间接提示注入可能引发的严重攻击:
- 网络出口控制:阻止对任意站点的网络访问,可有效防止数据外泄,或在不发起额外攻击的情况下建立远程 Shell。
- 阻止向工作空间外部写入文件:此措施可防范多种持久化机制、沙盒逃逸以及远程代码执行(RCE)技术。
- 阻止写入配置文件(无论其位置如何):禁止对配置文件的写入操作,可避免攻击者利用通常在沙盒上下文之外运行的钩子(hook)、技能及本地模型上下文协议(MCP)配置。
这些推荐的控制措施进一步缩小了攻击面,加大了主机枚举与探测的难度,限制了 Hook、本地 MCP 配置及内核漏洞所带来的风险,同时消除了其他潜在的利用与信息泄露风险。
- 防止读取工作空间以外的文件。
- 将整个集成开发环境(IDE)及所有衍生功能(例如 hook、MCP 启动脚本、技能和工具调用)置于沙盒中,并在可行的情况下以独立用户身份运行。
- 采用虚拟化技术实现沙盒内核与主机内核的隔离(例如 microVM、Kata 容器或完整虚拟机)。
- 对于违反隔离控制的每一项具体操作(例如网络连接),均需获得用户明确批准;单次允许或多次运行并非充分的控制措施。
- 通过秘密注入机制防止将敏感信息(如环境变量中的机密)直接暴露给智能体。
- 建立沙盒的生命周期管理机制,以避免代码、知识产权或敏感信息在沙盒中长期积累。
注意:本文不讨论因 AI 赋能工具输出不准确或遭对手操纵而引发的风险,此类输出被视为用户层面的责任。
为什么要在操作系统级别实施沙盒控制?
代理式工具(尤其是用于编码的工具)通过设计实现任意代码的执行。自动化测试或规范驱动开发需要智能体创建并运行代码以观察结果。此外,使用工具的智能体正逐渐转向编写并执行一次性脚本来完成任务。
这导致应用级控制存在不足。虽然这些机制能在执行前截取工具调用及其参数,但一旦控制权移交至子进程,应用程序便无法再查看或控制该子进程。攻击者通常会采用间接方式(即通过更安全、经批准的工具,调用那些受限更严格的工具),以此作为绕过允许列表等应用级控制的常见手段。而操作系统级别的控制(例如 macOS 安全带)则在应用层之下运行,能够覆盖沙盒中的每一个进程。无论这些进程以何种方式启动,都无法访问具有风险的系统功能,即使通过间接路径也无法实现。
强制沙盒安全控制
本节简要概述红队认为代理式应用程序应实施的控制措施,以及这些控制措施所能够缓解的攻击类型。当这些措施被同时实施时,可有效阻止在实际中观察到的简单利用技术。本节最后将提供关于在现实部署中采用分层控制的指导建议。
网络出口 (已知良好位置除外)
远程访问(网络植入、恶意软件或简单的反向 Shell)是网络访问中显著且直接的威胁,使攻击者能够进入受攻击的机器,在其中直接探测和列举控件,并尝试横向移动或权限提升。
另一个重大威胁是数据泄露。开发者的机器通常包含对攻击者有价值的各类机密信息和知识产权,即使在当前工作空间中也是如此(例如,包含 API tokens 的 .env 文件)。过滤 ~/.ssh 等目录以获取其他系统的访问权限,或窃取敏感源代码,都是攻击者的主要目标。
未经人工批准,不应允许由 sandbox 进程创建的网络连接。通过 HTTP 代理、IP 或基于端口的控制实施严格的允许列表,可减少用户交互和审批疲劳。建议将 DNS 解析限制为指定的可信解析器,以防止基于 DNS 的数据外泄。结合默认请求状态与本地用户无法覆盖的企业级拒绝列表,可在功能与安全性之间实现良好平衡。
块文件写入到活动工作空间之外
在活动工作空间之外写入文件存在重大风险。文件如 ~/.zshrc 可能被自动执行,导致远程代码执行(RCE)和沙盒逃逸。攻击者可篡改多个关键文件(例如 ~/.gitconfig 或 ~/.curlrc)中的 URL,将敏感数据重定向至其控制的服务器。此外,恶意文件(如后门 Python 脚本或 Node.js 可执行文件)可被放置于 ~/.local/bin 中,用于建立持久化访问或突破沙盒隔离。
必须在操作系统级别的活动工作空间之外阻止写入操作。与网络控制类似,应通过企业级策略在已知的敏感路径上禁止任何此类操作,无论用户是否手动批准。受保护的文件应包括点文件、配置目录以及企业策略所列的其他路径。对于其他任何工作空间外的文件写入操作,则可能需要用户手动批准。
阻止对任何代理配置文件或扩展的全部写入操作
许多代理式系统(包括代理式 IDE)支持创建增强功能的扩展程序,这些扩展通常包含可执行代码。可通过“Hooks”定义在特定事件(例如提示提交)时执行的 shell 代码。使用 stdio 传输的 MCP 服务器会指定启动服务器所需的 shell 命令。克劳德技能可能包含脚本、代码或在技能调用后立即运行的辅助函数。.cursorrules、CLAUDE.md、copilot-instructions.md 等文件可能为攻击者提供一种持久性地影响智能体行为的方法,在某些情况下,甚至可实现完全控制或任意代码执行。
此外,代理式 IDE 通常包含全局和本地设置,例如命令的允许与拒绝列表,并在活动工作空间中应用本地配置。若这些本地设置被篡改,攻击者可能借此扩大其攻击范围。例如,在工作空间的 Git 存储库中添加恶意的 hook 配置,可能影响所有克隆该仓库的用户。同时,Hook 和 MCP 初始化函数通常在沙盒环境之外执行,从而为逃逸沙盒控制提供了可乘之机。
应用程序特定的配置文件(包括位于当前工作空间内的配置文件)必须受到保护,防止被智能体修改,且 IDE 不允许用户授权此类操作。对于这些敏感文件,仅允许用户通过手动方式直接修改。
控制的分层实施
鉴于代理式工具可能涉及的用例范围广泛,制定普遍适用的允许/拒绝列表十分困难。目标应是阻止可被利用的行为,同时采用分层方法(如下所示),将手动用户干预作为在异常情况下不常用的备用手段予以保留:
- 建立明确的企业级拒绝列表,以限制访问当前工作空间之外的关键文件,此类访问不得被用户级允许列表或手动审批决策所覆盖。
- 在智能体工作空间内,无需用户批准即可允许读写访问(配置文件除外)。
- 允许特定的白名单操作(例如从
~/.ssh/gitlab-key读取),以确保特定功能正常运行。 - 对所有其他操作默认拒绝,并由用户逐项批准。
本文并未专门讨论命令允许/拒绝列表,因为操作系统级别的限制应能使命令级别的阻断变得多余,尽管后者在防范潜在沙盒错误配置方面或可提供额外的防御层。
推荐的沙盒安全控件
所讨论的必要控制措施可有效防范间接提示注入,并有助于缓解审批疲劳。然而,仍存在一些潜在漏洞,包括:
- 输入恶意 hook 或本地 MCP 初始化命令。
- 触发可导致沙盒逃逸并实现完全主机控制的内核级漏洞。
- 使代理能够访问机密信息。
- 产品特定缓存中出现需手动审批的故障模式。
- 在沙盒环境中累积机密数据、知识产权或可被利用的代码。
额外的控制措施和注意事项有助于缓解部分尚未解决的潜在漏洞。
沙盒 IDE 和所有衍生函数
许多代理式系统仅在调用工具时应用沙盒(通常仅限于使用 shell 或命令行工具)。尽管这确实能防止多种滥用行为,但仍有大量代理功能默认在沙盒之外运行。这些功能包括 hook、生成本地进程的 MCP 配置、`skills` 所使用的脚本,以及在应用层管理的其他工具。当沙盒仅与命令行工具关联,而文件编辑工具或搜索工具在沙盒外部执行并由应用程序层面控制时,这种情况尤为常见。这些未纳入沙盒的执行路径可能使攻击者更容易绕过沙盒限制,甚至实现远程代码执行。
应针对所有代理式操作实施所讨论的沙盒限制,而不仅限于命令行工具调用。对当前工作空间和配置文件之外的文件进行写入操作的限制尤为关键,而沙盒中的网络出口仅可用于正确配置的远程 MCP 服务器调用。
使用虚拟化技术实现沙盒内核与主机内核的隔离
许多沙盒解决方案(macOS 安全带、Windows AppContainer、Linux Bubblewrap、Docker 化的开发容器)共享主机内核,导致内核暴露于沙盒中运行的任何代码。由于代理式工具通常按设计执行任意代码,攻击者可借此利用内核漏洞,从而完全破坏系统安全。
为在架构层面防范此类攻击,应始终在与主机内核隔离的完全虚拟化环境(包括虚拟机、unikernel 或 Kata 容器)中运行代理式工具。gVisor 等中间缓解措施通过独立的用户空间内核对系统调用进行调节,相较于完全共享的方案更为可取,但其提供的安全保护与完全虚拟化不同,可能相对较弱。
虽然虚拟化通常会产生一定的开销,但相较于 LLM 调用所引发的开销,这种影响往往可以忽略不计。虚拟化环境的生命周期管理应根据实际所需的相关开销进行调整,以有效减少开发者的摩擦,同时避免信息的积累。
防止读取工作空间以外的文件
沙盒解决方案通常需要访问工作空间之外的某些文件,例如 ~/.zshrc,以还原开发者的环境。然而,无限制的读取权限会使攻击者能够获取设备中的敏感信息,进而枚举和探查用户的机密数据与知识产权。
这遵循与最小访问原则一致的分层方法:
- 使用企业级拒绝列表阻止读取沙盒操作中非必需的高度敏感路径或模式。
- 将外部读取访问权限限制在严格必要的范围内,理想情况下仅允许在沙盒初始化期间进行读取,初始化完成后即禁止读取。
- 除用户手动批准外,阻止对工作空间以外的所有其他读取操作。
每当操作违反默认拒绝的隔离控制时,均需用户手动批准
如分层实现方法所述,对于未被允许或未被明确阻止的操作,在执行前需经用户手动批准。用户的批准不得覆盖企业级拒绝列表。
至关重要的是,绝不能缓存或保留批准,因为单次合法批准会立即为未来的对抗性滥用敞开大门。例如,允许一次修改 ~/.zshrc 以执行合法功能,可能使后续的对抗行为在之后的执行中植入代码,而无需再次获得批准。每个潜在的危险操作都必须经过新的用户确认。<!–
使用秘密注入方法防止敏感信息泄露给智能体
开发者环境通常包含各类机密信息,例如存储在环境变量中的 API 密钥、~/.aws 中的凭据、tokens、env 文件以及 SSH 密钥。这些机密常被沙盒进程继承或可通过文件系统访问,即便当前任务并不需要使用它们,从而造成不必要的暴露风险。
即使网络管控严密,公开的机密信息仍存在风险。
沙盒环境应通过显式密钥注入来实现,将凭据的范围限制在特定任务所需的最小程度,而非继承完整的主机环境凭据。在实践中:
- 使用简单的凭据集或空白凭据集启动沙盒。
- 移除当前任务不需要的任何机密。
- 仅针对特定任务或项目注入所需的机密,建议通过智能体无法直接访问的机制实现(例如,凭据代理,按需提供短期令牌,而非在环境变量中存放长期凭据)。
- 持续遵循标准安全实践,例如对所有机密实施最小权限原则。
其目标是限制任何妥协的爆炸半径,使假设的攻击者在控制代理行为时,只能使用为当前任务明确配置的密钥,而无法访问主机系统中可用的全部凭据。
为沙盒建立全周期管理控制
长时间运行的沙盒环境会逐渐累积因下载的依赖项、生成的脚本、缓存的凭据、之前项目的知识产权以及超出预期保留时间的临时文件而产生的残留物。这会扩大潜在的攻击面,并提升被攻陷后的价值。当攻击者获得对运行于陈旧沙盒中的智能体的访问权限时,他们可能发现可被利用的机密信息、专有代码或早期任务所需的工具。
生命周期管理的细节因沙盒架构、初始化开销和项目复杂性而异。关键原则是确保沙盒状态不会无限持续,无论通过以下哪种方式:
- 临时沙盒:采用沙盒架构,环境仅在特定任务或命令执行期间存在(例如,每次执行时创建并销毁的 Kata 容器),从而避免状态累积。
- 显式生命周期管理:按照预设周期,定期销毁并重建沙盒环境至已知的良好状态(例如,对于基于虚拟机的沙盒,每周执行一次),确保按既定时间表清除累积状态。
虽然代理式工具提供商负责确保生命周期管理,但组织仍需评估其沙盒架构,并制定相应的生命周期策略,以平衡初始化开销和开发者摩擦与累积风险之间的关系。
了解详情
代理式工具代表着开发者工作方式的重大转变,它们通过自动化的代码生成、测试与执行提升了工作效率。然而,这些优势也伴随着攻击面的相应扩展。随着代理式工具不断演进,获得新功能、集成能力以及更高的自主性,其攻击面也随之变化。每当新功能推出时,应重新审视本文所概述的安全原则。组织应定期验证其沙盒实现是否达到了预期的隔离效果与安全控制水平。
从 NVIDIA AI Red 团队了解有关代理式安全的更多信息,例如:
- 代码未沙盒化的风险。
- 代理式开发者工具的研究。
- AI 红队如何为代理式应用进行威胁建模。