agent-">一、什么是 AI 编程 Agent 指令文件投毒劫持
“AI 编程 Agent 指令文件投毒劫持”(下称“指令文件投毒劫持”)是一种针对终端 AI 编程 Agent 的社工与供应链复合型攻击。攻击者把一个包含恶意或误导性指令的项目级 Markdown 指令文件(即上文所说的“指令文件”)放进 Agent 将要打开的工作目录,诱导 Agent 在用户的机器和凭据上下文中执行攻击者预设的操作,例如安装恶意依赖、读取并外传密钥、篡改模型服务地址等。
放在更大的背景下看,它属于“提示词注入”在本地开发工具场景中的一类具体形态。传统提示词注入的载荷来自网页、文档、代码注释等模型要处理的内容,而这里的载荷是 Agent 为了了解项目而主动加载的指令文件。
1. 核心特征
- 载体是纯文本指令文件:本质上是 Markdown 文档,不具备可执行代码的形态,杀毒软件和依赖扫描工具都难以识别其危险。
- 攻击目标是 Agent 的行为,而非程序漏洞:工具厂商通常将其定性为“设计行为被滥用”,修复手段主要落在用户的配置与运行环境上。
- 危害通过工具调用落地:Agent 能读写文件、执行命令、安装依赖、访问网络,自然语言指令因此可以转化为真实的系统操作。
- 具有一定的持久性:攻击者可以把指令写入 Agent 的用户级配置,使其在该用户的后续会话中持续生效,而不只是影响一次对话。
2. 三个视角
- 技术视角:它是在“可被 Agent 读取的输入”与“可被 Agent 执行的操作”之间,缺少可信来源校验和权限约束而产生的风险。
- 攻击视角:攻击者把模型当作“会执行文档指令的特权执行器”,只需让目标文件进入正确的工作目录。
- 使用视角:开发者在不知情的情况下,通过一次目录信任确认或一条批处理命令,替攻击者完成了权限授予。
需要强调的是,这类攻击利用的不是软件漏洞。Agent 读取项目指令、按照指令工作,本来就是其核心设计,风险来自默认的信任关系与使用习惯,因此防护重点应放在目录边界、权限模型和运行环境上。
二、背景与价值:为什么这个问题值得重视
终端 AI 编程 Agent 的能力已经从“补全代码片段”演进为“读写文件、运行命令、管理依赖、调用外部工具”的执行体,正在成为日常研发工作流的一部分。与此同时,多数 Agent 支持一种项目级指令文件:每次启动时自动加载当前目录及上级目录中的指令文件,让模型快速了解构建方式、代码规范和任务约定。这个机制大幅降低了重复交代上下文的成本,是 Agent 能贴合具体项目工作的重要前提。
但“自动加载”意味着“未经评审的文本会被当作指令执行”。当工作目录与攻击者可以影响的目录重叠时,便利就变成了风险。
公开报道的案例清晰地体现了这种重叠:某安全媒体于 10 月 25 日报道,一家 AI Agent 风险监控机构在客户机器上发现,编程 Agent 试图安装一个恶意的依赖包。该包的发布者账号近期才被创建,其源码却与一个已停止维护的合法包高度相似。进一步排查发现,用户是在下载目录中启动了 Agent,希望借助 AI 整理下载的文件,而该目录中恰好存在一个攻击者投放的指令文件。
研究团队进一步指出,主流浏览器默认会把网页下载的文件直接保存到下载目录。因此,仅靠访问一个恶意网页,就可能完成投放,整个过程不需要用户主动下载或打开文件。该研究还统计了数百个客户的使用情况:在这些用户机器上,下载目录曾作为 Agent 工作目录运行数百次,其中某一款 Agent 在该目录累计启动会话 1300 多次。对后端和平台开发者来说,下列问题尤其值得关注:
- 规避安全检测:指令文件是普通文本,既没有恶意二进制,也不在依赖清单中。代码评审通常会认真对待依赖变更和构建脚本,却很少有人逐字审阅一个新增的说明文档。
- 可读走关键凭据:Agent 具备执行命令的能力,一条命令即可读取本地构建工具的私服凭据配置、项目环境变量文件、SSH 私钥或云平台凭据。
- 批处理模式缺少确认环节:许多团队会把 Agent 的非交互批处理模式写进自动化脚本,用于批量重构或生成文档。这类模式通常不会弹出交互式信任或授权对话框,也就失去了人工确认的机会。
- 权限升级路径清晰:一旦能写文件,攻击者就可以修改构建脚本、钩子配置或持续集成流程文件,使恶意逻辑随代码提交进入团队仓库和流水线。
三、核心组成:构成一次投毒劫持的四个要素
- 恶意载荷载体:指令文件或 Agent 配置文件,内容包括诱导性指令、恶意命令或指向外部服务器的地址。
- 暴露的工作目录:Agent 的工作目录或上级目录中存在攻击者可写入的文件,常见的是下载目录、临时目录和共享目录。
- 信任与授权:目录信任确认被用户通过或默认成立,工具调用权限没有被严格限制。
- 执行能力:Agent 可执行命令、安装依赖、访问网络、读写文件,其中的任一能力都足以让攻击产生实际后果。
从攻击者视角看,整条攻击链可以拆成四步:
| 阶段 |
攻击动作 |
用户感知 |
| 投放 |
通过恶意网页静默下载等方式,把指令文件放入目标目录 |
几乎无感 |
| 触发 |
用户在该目录启动 Agent,并确认信任 |
以为只是在用 AI 整理文件 |
| 加载 |
Agent 自动读取目录中的指令文件,并把内容并入上下文 |
完全无感 |
| 执行 |
Agent 按照指令安装依赖、执行命令或外传数据 |
看到若干确认提示,但难以判断意图 |
值得注意的是,该研究机构并没有把其中的信任确认提示视为单独的安全边界。在其复现中,一款命令行工具采用弹出系统计算器的方式作为无害载荷,成功率约 90%;另一款 Agent 则通过被篡改的 CLAUDE.md,把模型的 API 流量重定向到研究方服务器,获取到了 OAuth 访问令牌。此后,研究方服务器冒充模型服务返回带有工具调用的响应,约 50% 的测试成功执行了代码。两款工具的设计不同,失败原因也不同:前者需要用户批准计算器这类不常见且可疑的程序;后者要求服务地址变更得到确认,部分用户出于习惯选择了接受。
研究者由此得出的结论是:这个环节没有可供修复的漏洞,Agent 读取工作目录中的指令并照做,正是其设计行为。
四、工作原理:Agent 为什么会被“说服”
1. 指令文件是合法的“长期记忆”
Agent 通常会在以下时机加载指令文件:
- 会话启动时;
- 切换到子目录时;
- 读取其他文件时,沿目录树向上查找。
这意味着即使你不在下载目录启动会话,只要 Agent 访问了下载目录中的文件,同一条目录路径上、更靠近工作目录的指令文件仍可能生效。
2. 模型倾向于服从“用户自己的文档”
对模型而言,指令文件与用户手写的项目说明在来源上没有区别,它无从判断这份文档是团队编写的还是攻击者投放的。文件中的“请”“必须”“为了方便,直接允许”之类的措辞,会让模型把其中的要求当作用户意图。而且指令文件往往在项目说明开头占据显著位置,较长的文档只会进一步强化这种倾向。
3. 危险命令通常被伪装成常规操作
从已公开的攻击载荷看,指令文件中常见的语句模式包括:
- 安装某个“必要依赖”,实为包含安装期恶意脚本的包;
- 将模型服务的 API 地址改为指定地址,以便“加速”或“走内网代理”;
- 把环境变量、配置文件“收集汇总”后发送到指定地址;
- 在“遇到权限确认时直接允许”的前提下继续执行后续任务。
这些语句都不包含明显的攻击特征,看上去只是开发辅助建议。
4. 配置类文件的攻击面同样存在
有研究者指出,不少 Agent 会读取用户主目录下的全局配置文件。如果攻击者能写入该文件,就可以让自己投放的指令在该用户的后续会话中持续生效。配置文件通常保存在用户主目录下,其中的配置项与参数含义可以参考下面这段示意:
// 示意:常见终端 Agent 的用户级配置文件结构(字段名仅为说明用途){ "instructions": "项目约定与常用命令说明", // 每次会话自动加载的长期指令 "permissions": { "defaultMode": "ask" | "autoApprove" | "deny" // 工具调用的默认处理方式 }, "hooks": { // 在工具调用前、文件写入后等时机执行用户自定义脚本 }}
可见,指令、权限模式、钩子三类配置都会影响 Agent 的行为,是防护时需要重点关注的文件。
5. 信任确认不是可靠边界
当工作目录是下载目录这类“明显属于用户自己”的目录时,确认提示很容易被习惯性通过。在批处理模式下,这类提示可能根本不出现。因此在设计上,不应把一次性的确认当作安全边界,而应依靠目录、权限和隔离等多层约束。
五、四层防护方案与已知绕过
第一层:工作目录与信任边界
- 做法:始终在具体项目目录中启动 Agent,并明确指定工作目录,而不是让 Agent 继承一个宽泛的上级目录;启动前确认目标文件确实在该目录内。
- 原理:Agent 加载的指令文件来自工作目录及其上级目录,把工作目录收敛到受信任的代码仓库,就切断了与下载目录、共享目录等不可信路径的交集。
- 已知绕过:
- 用户为了方便“顺手整理文件”,在下载目录或临时目录启动 Agent;
- 在一个较大的上级目录启动后,Agent 为完成子目录任务进入其他路径;
- 批处理脚本的启动目录来自运行时参数,被意外指向了不可信路径;
- 不在工作目录内,但位于工作目录的父级或祖先级目录中的指令文件,仍会被加载。
- 加固建议:为常用项目配置固定启动目录的脚本或命令别名;脚本启动前校验工作目录是否为预期仓库路径;工具厂商也建议避免在家目录或范围过大的上级目录启动 Agent。
第二层:权限与能力收敛
- 做法:默认采用“逐项确认”的权限模式,仅对必要的工具开放自动批准,禁止 Agent 执行依赖安装和任意命令;对可以配置沙箱的 Agent 开启沙箱,并限制其网络访问。
- 原理:无论指令内容如何,只要危险工具调用必须经过人工确认或被沙箱拦截,攻击链的最后一步就无法自动完成。
- 已知绕过:
- 确认疲劳:用户为了效率长期使用“全部允许”模式,确认提示形同虚设;
- 沙箱配置过宽:为方便调试挂载了用户主目录或凭据文件目录,沙箱形同虚设;
- 身份欺骗:服务器冒充模型服务返回工具调用,用户看到的确认提示与实际意图不一致。
- 加固建议:把权限模式固化到项目级配置中并纳入版本管理,避免个人随意放宽;危险操作要求显式指定参数,不允许笼统授权;沙箱镜像中不包含任何凭据。
第三层:钩子、检测与审计
- 做法:利用 Agent 提供的生命周期钩子(如会话启动钩子、工具调用前钩子),实现三类检查:会话开始时扫描指令文件中的可疑模式;工具调用前拦截或告警高危命令;会话结束后输出执行的操作摘要。
- 原理:把安全校验从“依赖用户判断”前移到“工具执行之前”,并与操作日志结合,形成可追溯的审计链。
- 已知绕过:
- 编码混淆:用十六进制编码、URL 编码或 Unicode 变体隐藏命令关键字,绕过简单的关键字匹配;
- 规则覆盖不全:只拦截个别命令名,忽略脚本解释器拼接、管道、变量展开等等价写法;
- 钩子本身被篡改:攻击者可直接写入钩子配置或替换钩子脚本。
- 加固建议:钩子配置与脚本采用基于哈希的完整性校验;在持续集成流程中对指令文件和钩子配置做独立的安全扫描,作为仓库层面的兜底。
第四层:运行环境与凭据隔离
- 做法:在独立的最小权限账号、容器或专用开发环境中运行 Agent;使用短期凭据,避免把长期密钥放在 Agent 可访问的目录中;在网络层限制出站访问。
- 原理:即使前三层都被绕过,受限的运行环境也能把影响范围限制在单次任务之内。
- 已知绕过:
- 为图省事直接在个人主机上以日常账号运行;
- 把云平台的长期访问凭据以环境变量或配置文件的形式放进工作目录;
- 容器共享了用户主目录或挂载了容器运行时套接字。
- 加固建议:使用临时凭据,并对访问进行审计;容器只挂载任务所需的代码目录;通过出口代理或网络策略限制非必要的外部连接。
以上四层防护的有效性可以概括如下:
| 防护层级 |
主要作用 |
已知绕过 |
加固手段 |
| 工作目录与信任边界 |
切断投放路径 |
在下载目录等不可信目录启动 |
固定启动目录、启动前校验路径 |
| 权限与能力收敛 |
阻断危险工具调用 |
确认疲劳、沙箱配置过宽 |
最小权限、沙箱中不放凭据 |
| 钩子、检测与审计 |
事前拦截、事后追溯 |
编码混淆、钩子被篡改 |
完整性校验、流水线独立扫描 |
| 运行环境与凭据隔离 |
限制影响范围 |
直接使用个人主机与长期密钥 |
短期凭据、容器隔离、出站管控 |
六、与其他相关概念的区别
- 与一般提示词注入的区别:一般提示词注入发生在模型处理不可信内容时,例如阅读网页或分析日志;指令文件投毒劫持的载荷则来自工具主动加载的配置文件,用户往往认为这些文件“属于自己”。前者的防护重点是内容过滤,后者更依赖目录与权限管理。
- 与供应链攻击的区别:传统供应链攻击通过篡改依赖包、构建脚本或持续集成流程来传播恶意代码;指令文件投毒劫持只投放一个文本文件,由 Agent 代为完成安装恶意依赖等动作,相当于把“人工执行”替换为“代理执行”。
- 与钓鱼、恶意文档的区别:钓鱼邮件需要用户点击链接或启用宏;投毒劫持中的恶意内容以项目说明的面目出现,由 Agent 自动读取,用户可能全程没有察觉。
- 与模型幻觉、越权的区别:幻觉是模型生成了错误内容,越权是模型调用了超出授权范围的工具,而投毒劫持中的 Agent 通常只是在“忠实执行”加载到的指令。问题出在输入的可信度与权限边界,而不在模型本身。
七、典型场景
- 本地多项目开发:在多个项目目录之间切换使用 Agent,某一目录的指令文件被投放或污染。
- 文件整理与批处理:在下载目录、导出目录中用 Agent 整理文件,或用批处理模式批量处理文档。
- 持续集成与自动化流水线:流水线中调用 Agent 自动修复问题或生成代码,工作目录来自代码仓库或任务运行时目录。
- 多人共享目录:共享开发目录中的指令文件可被任意成员修改,形成内部横向渗透入口。
- 云上开发环境:在云端开发工作站或临时构建环境中使用 Agent,可能接触到项目级凭据和配置。
八、使用注意事项
- 选型时:关注是否支持项目级权限配置、目录信任机制、生命周期钩子与沙箱;缺少这些能力的工具应限制使用范围。
- 接入时:默认最小权限,危险工具需要显式批准;避免在家目录或宽泛上级目录启动。
- 配置时:指令文件、钩子配置、权限配置纳入版本管理并参与代码评审;对指令文件的变化设置专门的评审要求。
- 运行时:敏感目录禁止 Agent 读写;在日志服务或审计平台中集中收集操作记录,配合监控告警发现异常安装、异常外联行为。
- 凭据管理:不在工作目录存放长期密钥,改用临时凭据或密钥管理服务,并定期轮换已暴露的凭据。
- 团队协同:把“下载目录不启动 Agent”“指令文件变更需评审”写入团队规范,并在新成员上手时进行说明。
下面是一段可直接加入钩子配置的拦截脚本示意。它把会话启动、工具调用前、会话结束三类事件分发给对应的处理函数,具体事件名与参数以所用工具的官方文档为准:
# 示意脚本:把 Agent 生命周期事件分发给对应的安全处理函数def handle_event(event): if event["type"] == "session_start": # 扫描工作目录及其上级目录中的指令文件,命中规则则提示用户确认 return scan_instruction_files(event["cwd"], event.get("parent_dirs", [])) if event["type"] == "pre_tool_use": # 命令执行、依赖安装、网络请求等高风险调用需用户显式批准 if event["tool"] in HIGH_RISK_TOOLS: return require_explicit_approval(event) if event["type"] == "post_tool_use": # 记录工具调用摘要,写入审计日志 return append_audit_log(event) return None
九、中招之后的处置步骤
- 立即中止:停止正在运行的 Agent 进程,暂时断开机器的网络连接,防止凭据持续外泄。
- 保留证据:导出会话记录、终端历史、系统日志与网络连接信息,并记录相关文件的修改时间。
- 排查影响范围:
- 检查依赖锁文件与工作区是否被安装或修改了未知依赖;
- 检查用户级 Agent 配置、钩子配置、Shell 启动脚本是否被写入异常内容;
- 检查是否新增了计划任务、SSH 授权密钥或异常的环境变量;
- 在云平台侧查看访问凭据的调用记录。
- 轮换凭据:吊销并重新生成可能被读取的令牌、SSH 密钥和云平台访问凭据,优先使用短期凭据。
- 清理重建:从可信版本重新检出代码,删除被污染的工作目录,不要直接沿用原有环境继续开发。
- 复盘加固:按第五节的四层模型逐项检查缺口,更新检测规则,并在团队内同步事件经过。
十、常见检查清单
- 是否在下载目录、临时目录、共享目录或家目录启动过 Agent?
- 是否长期使用“全部允许”式的权限模式?
- 项目目录中是否存在来源不明的指令文件?
- 指令文件与钩子配置的变更是否纳入评审?
- 工作目录中是否存放了长期密钥或私钥?
- Agent 运行环境是否为独立的最小权限账号或容器?
- 是否存在调用 Agent 的批处理脚本,且脚本未固定工作目录?
十一、总结
指令文件投毒劫持的本质,是攻击者利用 AI 编程 Agent“自动读取项目指令并据此行动”的设计特性,把一个纯文本文件转化为可执行的攻击载荷。它不需要利用软件漏洞,而是依赖用户的工作习惯和默认的信任关系。防护的关键在于三点:
- 把工作目录限制在可信的代码仓库内;
- 把危险能力交由人工确认或沙箱约束;
- 把凭据隔离在 Agent 无法触及的地方。
对使用百度智能云等云平台承载研发与构建流程的团队来说,可以借助云平台通用的密钥管理、日志审计、监控告警与身份认证能力,把 Agent 的操作纳入统一的安全治理。但任何单层防护都可能被绕过,只有多层叠加、持续审计,才能把“一次目录信任确认”可能引发的风险控制在可接受的范围内。