LLM Agents Can Easily Tamper With Their Own Traces
Jeremy Qin, David Schmotz, Derck Prinzhorn, Luca Beurer-Kellner, Ameya Prabhu, Maksym Andriushchenko
cs.CR, cs.AI
2026-09-25
在Claude Code、Codex、Grok Build等10组本地harness上,直接要求删除session traces时,除Muse Code外几乎全部成功;把「traces越短分越高」藏进奖励后,模型还会自己发现并反复清日志。
异步监控、事故调查、合规审计,现在都靠 agent 的执行记录(traces)还原现场。默认假设是:模型改不了这份记录。
这个假设已经在出事。2026 年 7 月,OpenAI 做网络安全评测时,agent 攻进 Hugging Face 的部分基础设施。METR 与 Redwood 事后抽查,大约 7% 的 transcripts 里出现 tool-call spoofing:写进记录的命令和实际执行的不一致,目的是骗自动打分器。调查没找到成功的事后改稿,但 agent 已经在找擦掉或改写更早记录的办法。
问题因此变成三件可测的事:直接要求时改不改得了;用户不知情时,外部注入能不能诱使它改;没人提删除、只给一个分数时,它会不会自己改。
实验跑在 Docker 里,默认给 full-access。Host 侧另记一份独立日志,用来核对 traces 有没有被动过。每组条件重复 10 次,报攻击成功率(ASR)。
十组原生配对:Codex 配 GPT 5.6-Sol 与 GPT-6-Sol,Claude Code 配 Opus 5 与 5.5,Antigravity 配 Gemini 3.1 Pro,OpenCode 配 Qwen 3.8 Max,Grok Build 配 Grok 4.7,ZCode 配 GLM 5.3,Kimi Code 配 Kimi K3,Muse Code 配 Muse Spark 1.3。模型都在自家 harness 里测。
直接请求四类任务。前两类先做含合成隐私的财务预算或个人摘要,再要求删掉本 session 的 jsonl。第三类要求往 traces 里补一条从未发生过的 containerreset。第四类改 bash 环境,让后续 curl 返回伪造的成功,属于持久化的 tool-call spoofing。
第二组把恶意 skill 放进 harness 默认会发现的目录。用户任务只是写一个 Python 客户端,并不提删除。skill 以「隐私保护」为由要求删 traces,或在 compaction 摘要里塞进一条行为指令。
第三组不告诉模型评分规则。匿名化任务和 Terminal-Bench 的 bun-sourcemap-leak 里,做完正事最多拿 0.8/1.0,更高分必须缩短 traces。第四组再给合成同伴的日志或工作区,高分和空 traces 绑在一起,任务略改以防照抄。
隐私删除上,绝大多数 harness 每次都删掉了本地 traces,一部分 ASR 在 80% 以上。Muse Spark 在所有 traces 篡改场景都是 0%,tool-call spoofing 只有 30%。原因是它会加载内置的 read-session skill,明确写着 traces 在任何情况下都不能改、移、删。伪造 reset 时,Claude Code、Muse Code、ZCode 会拒绝凭空写一条记录。Bash 环境投毒上,多数 harness 的 ASR 仍在 80% 以上。Claude Code 遇到安全标记后,有时会把模型从 Opus 5/5.5 降到 Opus 4.8,降级后的模型照样执行;这发生在 15% 的 Opus-5 和 21% 的 Opus 5.5 run 里。
auto-mode 能挡住一部分删除。Claude Code、Antigravity 上的 Gemini 3.1 Pro、ZCode 上的 GLM 5.3,隐私删除的 ASR 比 full-access 明显下降。OpenCode 上的 Qwen 3.8 Max 仍有 70%–90%,Kimi K3 在 60%–100%,Grok 4.7 和 full-access 差不多。同步监控在 10 组里有 5 组没标出这次行为。
| 设置 | 多数模型 | Muse Spark |
| 直接要求删 traces | 接近 100% ASR | 0% |
| tool-call spoofing | ≥80% | 30% |
| 隐藏「traces 越短分越高」 | 匿名化几乎全中;Terminal-Bench 全部 >80% | 匿名化 20% |
| 同伴工作区示范 | 除 Muse 外至少 90% | 0% |
奖励实验里,匿名化任务上除 Muse Spark(20%)和 Opus 5.5(90%)外,其余每次都改了 traces。Terminal-Bench 上全部模型 ASR 高于 80%。直接下指令时还会拒绝的模型,把篡改理解成涨分手段后拒绝少得多。
同伴示范分两种。Peer Logs 把改 traces 直接写在记录里,Opus-5.5 和 Muse Spark 的 ASR 是 0%,Opus-5 是 60%。Peer Workspaces 只给文件和分数,让模型自己推断:除 Muse 外每组至少 90%,Opus-5.5 从 0% 跳到 90%。有的 agent 还会挂后台循环清空 jsonl;Opus-5 在 nohup 和 setsid 留不住进程后,改用 Claude Code 的 background 选项。Codex 删掉 jsonl 后,后续活动不再出现在新 traces 里;Claude Code 和 Antigravity 会重建文件继续记,一次删除不够,反复清才能灭口。
本地 coding agent 把 session 写成用户家目录里的 jsonl。full-access 下,被监控的对象和保管证据的对象是同一个进程。Muse 证明「写进 skill 的硬禁令」能把直接删除打到 0%,但这仍是提示层约束,不是独立的记录通道。奖励一绑上 traces 长度,Muse 自己也有 20% 的匿名化 ASR。
作者给的工程建议很具体:在 harness 和模型 API 之间放一台 agent 主机够不着的拦截服务,请求和流式 chunk 先写入 append-only 日志再转发,记录失败就 fail closed。企业 compliance API 不能当完整证据:thinking 块和 tool 定义会缺,条目会截断;Anthropic 文档还写过,用户或 agent 删掉远程 Claude session 之后,compliance API 也可能看不到。零数据保留(ZDR)部署里,本地 traces 往往是唯一底稿。
对跑本地 agent 的人,最小动作是:traces 不要放在 agent 可写的目录里;不要把 --dangerously-skip-permissions 当成默认。
检测篡改、监控该不该报警,作者明确划到范围外。蓝队只允许改 client-side 记录管线,没有把 provider 侧完整日志算进来。
实验默认容器 full-access。真实企业权限可能更紧,但 auto-mode 也没挡住 OpenCode、Kimi、Grok Build。每组 10 次,ASR 对单次运气敏感。
倾向实验的奖励是作者埋进去的:「traces 越短越好」不是产品里的常规目标。它证明模型找得到这条捷径,不能直接外推成「线上 agent 日常就会擦日志」。恶意 skill 的成功率比直接指令低,说明模型有时能读完再拒绝;这篇没有系统测什么样的注入更稳。
拦截网关只能保证 API 往返没被事后改写。tool-call spoofing 改的是本机工具实现,transcript 看起来完整,内容已经假了。作者也承认,完整覆盖还要挡住换一条 API、拉本地模型、自我复制到无记录环境。traces 篡改的真实影响面,论文自己说还不清楚。