Agent Sandbox 从零开始 · 3.0
第 11 / 34 节 · 面向零基础读者

第 9 章:验证边界,而不只是看到成功

为什么还要做失败实验

计算成功只能说明程序在当前环境能运行,不能说明限制都生效。边界测试需要提出一个应该被拒绝的动作,再观察系统是否真的拒绝。

先备份 input/analyze.py。每次实验只替换这个文件;运行前把旧报告移走,以免控制器误读上次的结果。不要把原始重要数据放进这些实验。

验证输入只读

把脚本临时改成:

from pathlib import Path
Path('/input/should-not-exist.txt').write_text('test')

再运行控制器。预期写入失败并出现只读文件系统或类似权限错误,任务非零退出。宿主机 input 目录不应出现该文件。不同系统的错误文字可能不同,判断重点是操作是否被拒绝。

验证根目录只读

from pathlib import Path
Path('/root-test.txt').write_text('test')

预期失败。因为程序同时以非 root 身份运行,错误可能来自权限或只读文件系统;这一条不能单独区分两个机制的贡献。它证明当前组合策略拒绝了该写入。

验证常规外部网络连接

import socket
try:
    socket.create_connection(('1.1.1.1', 443), timeout=3)
except OSError as exc:
    print('外部连接失败:', type(exc).__name__)
else:
    raise SystemExit('外部连接意外成功,请检查配置')

用 IP 地址可避免把 DNS 失败误当成所有网络限制的证据。预期连接失败。控制器随后还会提示没有报告,这是正常的:这个测试脚本没有生成报告。单次失败只是一个目标地址的检查;应结合 Docker 网络配置确认 –network=none,不能用一次失败证明所有可能外传通道都不存在。

验证超时停止

import time
time.sleep(120)

控制器等待约 30 秒后开始清理。Docker 客户端被终止不保证容器随之终止,因此 finally 中的 docker rm -f 很重要。执行后可运行 docker ps -a,确认没有残留 sandbox-demo- 开头的容器。

实验完成后恢复原来的分析脚本,再运行一次成功案例。记录“尝试了什么、预期如何、实际如何”,比只保存一个成功截图更有学习价值。

本书包含示例与资料导读;验证范围和来源见附录。