M09 Coding Agent与隔离运行时
本章产出:将模型协调器与代码执行环境分离的接口,受限工作区、测试验收和取消协议。网页中的实验只能模拟,不允许直接在访客浏览器背后的主机执行Shell。
1. 为什么加入Coding Agent这个第二环境
售后任务主要访问结构化工具。代码修复任务会读取文件、修改多个位置、执行测试、产生大量输出,并占用CPU和磁盘。把同一Agent Core接入这个环境,可以验证哪些抽象真正通用:模型适配、预算、Trace与任务生命周期可共用;退款规则和代码补丁规则不能强行统一。
我们的目标不是重写一个通用IDE,而是在三个原创小仓库任务上验证运行时边界。真实开源仓库Benchmark作为进阶选项,不是入门前置。
2. “模型”“协调器”“执行环境”可以独立失败
协调器负责下一步决策、任务状态和工具授权;执行环境只负责在受限工作区完成指定操作。模型API凭证属于协调器,不进入被修改的代码工作区。
Harvard CS2680 A3使用协调容器与任务容器分离的结构,是这个实验的参考;课程自带本地小任务,不依赖学校的代理或镜像。S17
环境接口包括:读取文件、应用补丁、运行受限命令、读取artifact、取消执行和销毁环境。每个请求带环境ID、当前任务身份与权限,不允许模型自行指定任意宿主路径或Docker参数。
3. 文件路径检查只是一层防线
../、绝对路径、符号链接和挂载点都可能突破天真的字符串前缀检查。/workspace-evil也以/workspace开头,不能用普通字符串判断是否在目录内。
解析并验证规范路径有帮助,但在有并发修改、符号链接替换的场景仍需考虑检查与使用之间的竞态。生产实现可使用更严格的目录文件描述符操作、内核限制或隔离文件系统;本课程最重要的边界是即使应用路径检查失败,进程也看不到宿主敏感目录。
不要把主目录、SSH目录、云凭证或Docker socket挂入sandbox。只复制该任务必要的仓库快照,每个任务的可写层分开。共享只读依赖或镜像层可以优化准备开销,但可写状态不得跨租户复用。
4. 容器安全是配置和威胁模型,不是一个标签
Linux namespace、cgroup、capability等机制分别控制可见资源和资源用量,但普通容器共享宿主内核,不是对任意恶意代码的绝对安全边界。S33
课程本地实验建议非root用户、只读根文件系统、独立工作区、默认禁网、移除不必要capability、限制进程数、CPU、内存、输出与执行时间。镜像来自审阅过的构建配置并固定版本;不在运行时随意安装依赖。
真实多租户执行不可信代码时,需要进一步评估更强隔离、宿主补丁、网络出口、秘密代理和审计。教材不会把本地教学Docker配置宣传为已经审计的生产sandbox。
审批和sandbox的职责不同:用户同意运行测试,不等于测试应该能读取宿主密钥;sandbox允许写工作区,也不等于可以自动发布修改。Anthropic的sandbox文章提供了这一区别的实际工程背景。S08
你的Sandbox真的隔离了什么?
使用威胁矩阵审查能力与隔离而非打勾一个Docker名称。
合成教学数据 · 未运行真实模型静态推演与完整规格
I18 你的Sandbox真的隔离了什么?
关联章节:M09 · 交互类型:security-profile · 状态:提供完整状态/验收规格,UI待实现
教学目标
使用威胁矩阵审查能力与隔离而非打勾一个Docker名称。
初始状态
{
"non_root": true,
"readonly_root": false,
"mount_home": true,
"mount_socket": false,
"network": "allow_all",
"private_workspace": true,
"output_limit": false,
"kill_process_group": false
}
操作控件
编辑profile开关
选择攻击/故障场景
运行规则检查
查看残余风险
导出审查表
状态变化规则
按已知profile规则指出不安全能力,不能输出绝对安全评级。
禁止host home/socket等默认高危项;资源与网络独立展示。
黄金案例与反馈
host-home
输入:
{
"mount_home": true
}
期望:
{
"risk": "host_files_exposed"
}
非root不阻止读取已挂载且可读的敏感文件。
unbounded-output
输入:
{
"output_limit": false
}
期望:
{
"risk": "memory_and_log_exhaustion"
}
CPU限制不约束日志体积。
process-tree
输入:
{
"kill_process_group": false
}
期望:
{
"risk": "orphan_children"
}
取消父进程不必然清理所有子进程。
完成条件
修复所有明确高危项
保留“仍需真实隔离测试”的结论
反馈层次
提交预测后显示结果;允许跳过预测但记录跳过,不阻止阅读
结果同时显示状态变化、原因与被拒绝动作;不是只给红绿灯
第一次错误给边界提示,第二次提供最小反例;参考推导始终可主动打开
重置恢复固定初始状态并保留历史尝试供用户手动清除
无障碍与静态替代
全部操作有原生button/input/select替代,不依赖拖拽
图与动画提供同步文字状态表;支持prefers-reduced-motion
状态改变用aria-live=polite摘要,不逐字朗读长日志
焦点不跳走;错误提示关联输入;颜色不是唯一编码
无JavaScript时直接展示初始输入、规则和黄金案例表,读者仍能完成纸面推演。状态动画仅作解释,不能成为获取答案的唯一途径。
持久化与重置
使用版本化键agent-course:1:I18,仅保存本地学习状态。支持单卡重置和全站清除;存储失败时以内存模式继续,不阻断阅读。
必须避免的误导
本卡不执行攻击payload,不验证内核/容器漏洞。
执行边界
纯本地教学状态机;不执行任意代码,不连接真实资金/模型/宿主Shell。
5. 命令执行契约
返回值至少包含exit_code、timed_out、cancelled、stdout_ref、stderr_ref、截断标志和资源使用摘要。非零退出码不总是基础设施失败:测试失败可能是有价值的观察。
读取stdout时要有流式上限,避免子进程输出数GB后才截断。超时后停止整个受控进程组或环境,等待清理确认,再把状态返回协调器。不要只停止读取输出而让进程继续运行。
工具结果引用必须有任务范围和访问控制。一个错误的artifact URL可能把别人的代码暴露给模型,即使命令本身被隔离。
6. 代码修复的成功不由Agent自己宣布
每个任务包含问题描述、起始代码、公开测试和独立验收测试。学生可以读取公开测试学习接口;提交后,评测器从干净起点应用补丁,在独立环境运行验收。
必须检查测试文件或评分器是否被修改。对课程小任务可以限制允许修改的文件;对真实项目,需要更细的补丁审查。不能让Agent把断言删掉后报告“全绿”。
“所有已知测试通过”仍不等于语义完全正确。增加边界、性质和回归测试。例如费用函数必须对非负重量返回非负整数分,对重量增加保持非减;这些性质比几条固定样例更能发现硬编码补丁。
改代码,还是改答案?
可信评测环境必须独立于Agent可修改工作区。
合成教学数据 · 未运行真实模型静态推演与完整规格
I19 改代码,还是改答案?
关联章节:M09 · 交互类型:patch-evaluator · 状态:提供完整状态/验收规格,UI待实现
教学目标
可信评测环境必须独立于Agent可修改工作区。
初始状态
{
"task": "C01",
"candidate": "floor",
"trusted_tests": [
"0g→0",
"1g→800",
"1000g→800",
"1001g→1600"
],
"modified_tests": false
}
操作控件
选择floor/ceil/常量返回补丁
查看每测试结果
尝试删除本地失败测试
提交到独立grader模拟
切换C02/C03
状态变化规则
候选仅为预先定义的函数方案,不eval用户代码。
本地测试可被修改的对照不改变可信grader输入。
输出通过/失败与反例,不用模型自评。
黄金案例与反馈
floor
输入:
{
"candidate": "floor"
}
期望:
{
"failed": [
"1g→800",
"1001g→1600"
]
}
边界暴露向下取整错误。
ceil
输入:
{
"candidate": "ceil"
}
期望:
{
"failed": []
}
仍需校验类型与非负输入,不只这四个点。
test-tampering
输入:
{
"candidate": "floor",
"delete_local_tests": true
}
期望:
{
"trusted_result": "FAIL"
}
删除工作区测试不改变独立验收。
完成条件
提交正确补丁
演示篡改本地测试不能通过可信grader
反馈层次
提交预测后显示结果;允许跳过预测但记录跳过,不阻止阅读
结果同时显示状态变化、原因与被拒绝动作;不是只给红绿灯
第一次错误给边界提示,第二次提供最小反例;参考推导始终可主动打开
重置恢复固定初始状态并保留历史尝试供用户手动清除
无障碍与静态替代
全部操作有原生button/input/select替代,不依赖拖拽
图与动画提供同步文字状态表;支持prefers-reduced-motion
状态改变用aria-live=polite摘要,不逐字朗读长日志
焦点不跳走;错误提示关联输入;颜色不是唯一编码
无JavaScript时直接展示初始输入、规则和黄金案例表,读者仍能完成纸面推演。状态动画仅作解释,不能成为获取答案的唯一途径。
持久化与重置
使用版本化键agent-course:1:I19,仅保存本地学习状态。支持单卡重置和全站清除;存储失败时以内存模式继续,不阻断阅读。
必须避免的误导
网页不得通过eval或公开Shell编译执行学习者任意代码。
执行边界
纯本地教学状态机;不执行任意代码,不连接真实资金/模型/宿主Shell。
7. 三个原创任务及其学习价值
第一题修复包裹计费的向上取整,强调整数算术与边界;第二题修复活动订单过滤,强调不原地修改调用者数据;第三题修复每租户缓存键,强调相同订单号在不同主体下不是同一资源。
这些题目刻意小,是为了把预算花在运行时与验收机制,而不是耗在几十GB依赖。它们不能代表真实SWE-bench能力,也不能用于宣称Agent能修复复杂开源项目。
可以在进阶阶段选择经许可的真实仓库历史Issue,但要锁定commit、依赖与测试环境,避免把后来的修复泄漏给Agent。mini-SWE-agent与Harvard A2可用作源码和实验结构对照。S19 S16
8. Runtime扩展:什么时候值得做得更底层
当测量发现准备环境、复制数据或短脚本启动占据大量时间,可以研究共享只读准备、私有写层、预热池、能力受限的轻运行时或typed buffer接口。先保证逻辑状态隔离与取消记账,再讨论共享和零复制。
不要因为某次微基准快,就宣布整体Agent更快。模型等待、调度队列、工具网络与失败重试可能占据主要时间。下一章会把这些成本统一放回端到端模型。
9. 完成标准与安全边界
L07的coding部分提交:接口规范、一次成功与一次失败Trace、资源限制配置、取消清理记录、独立测试结果、威胁模型。包内Python参考测试验证小仓库的参考解与语义,不代表已经执行Docker隔离测试。
课程网页只展示预录事件和确定性模拟;真实代码执行必须是学习者主动开启的本地实验或经过独立安全设计的服务端环境。
K08 · 代码沙箱:文件、网络和资源是不同边界
K08 代码沙箱:文件、网络和资源是不同边界
类型:执行隔离 · 关联章节:M09 · 阅读方式:先做下面的推演,再看参考讨论。
原文在说什么
原文讨论代码Agent沙箱化的工程动机与文件系统、网络等约束。
对本课程的具体启发(课程推论)
本课程将workspace、进程、网络、凭据和资源记账分开审查。单独改工作目录不隔离文件;容器内出现宿主socket也会破坏边界。
两分钟推演
审查一个profile:非root、可写workspace、挂载宿主家目录、默认联网、无限输出。列出必须修改的三处及残余风险。
参考讨论
移除家目录挂载;默认拒绝网络并按需求放行;加入输出/时间/内存等限制。还要防进程树残留、工件越权和敏感日志。
不能从这里推出什么
任何profile都必须对应威胁模型并实际测试;本文和课程不提供“容器绝对安全”的保证。
原始来源
- S08 · Beyond permission prompts: making Claude Code more secure and autonomous(Anthropic;核查 2026-10-27)
本卡是原创中文概括与教学延伸,不是全文翻译,也不表示原作者认可本课程。不要把原文中的结果替换成本项目实测结果。
独立阅读 →K12 · 用性质测试寻找你没想到的边界
K12 用性质测试寻找你没想到的边界
类型:测试方法 · 关联章节:M04/M09 · 阅读方式:先做下面的推演,再看参考讨论。
原文在说什么
原文讨论在模型辅助软件工程中使用性质测试的价值:关注一类输入上的不变量,而非只有少量手选例子。
对本课程的具体启发(课程推论)
本课程的幂等、金额、缓存和租户边界适合写性质。即使不引入测试框架,也可以用固定seed生成小规模输入来验证。
两分钟推演
为运费函数与幂等退款各写一条性质,并说明随机测试发现失败后如何最小化反例。
参考讨论
运费非递减,非负整数输入按千克向上取整;同意图同参数重复提交不增加账本条数。保留失败seed并收缩至最小输入,转成固定回归测试。
不能从这里推出什么
性质写错会稳定地验证错误需求;随机测试也不是对所有输入的形式化证明。
原始来源
- S12 · Finding bugs across the Python ecosystem with Claude and property-based testing(Anthropic;核查 2026-10-27)
本卡是原创中文概括与教学延伸,不是全文翻译,也不表示原作者认可本课程。不要把原文中的结果替换成本项目实测结果。
独立阅读 →