.agents/issue/sandbox/opensandbox-docker-security-review.md
审查日期:2026-05-23
这是当前 OpenSandbox Docker 沙盒安全工作的唯一文档。原 TDD 方案已合并到本报告中,不再单独维护,避免“方案文档”和“审查报告”结论不一致。
当前范围只覆盖 Docker runtime,不覆盖 Kubernetes/Helm。Kubernetes 的 RBAC、ServiceAccount、PodSecurity、NetworkPolicy、Pool/BatchSandbox 需要后续单独审查。
已经落地到代码的修复:
apiKey 非空。networkPolicy、extensions、resourceLimits、timeoutSeconds。/workspace,不再暴露挂载路径配置。sandbox 运行,并确保 /workspace 可写。已经撤销、当前没有落地的修复:
SANDBOX_API_KEY。bridge。127.0.0.1。dns+nft。因此当前结论是:代码层安全修复已有一部分完成,但 Docker 部署层仍未闭环。部署层没有落地前,不能认为生产 Docker 沙盒已经完成安全部署。
按最坏情况假设:
execute()。curl、git、node、python3、bun 等网络和脚本执行工具。核心安全目标:
execute() 存在,也不能因此读到宿主机、业务服务或安全密钥。修改点:
packages/service/core/ai/sandbox/provider/config.tspackages/service/test/core/ai/sandbox/provider/config.test.ts效果:
apiKey 为空会直接抛配置错误。限制:
AGENT_SANDBOX_OPENSANDBOX_API_KEY 和 OpenSandbox server [server].api_key 配成同一个强随机值。修改点:
sdk/sandbox-adapter/src/types/sandbox.tssdk/sandbox-adapter/src/types/index.tssdk/sandbox-adapter/src/adapters/OpenSandboxAdapter/type.tssdk/sandbox-adapter/src/adapters/OpenSandboxAdapter/index.tssdk/sandbox-adapter/tests/unit/adapters/OpenSandboxAdapter.test.ts效果:
SandboxCreateSpec 支持 networkPolicy、extensions。OpenSandboxAdapter.create() 会把 networkPolicy、extensions、resourceLimits 传给 OpenSandbox SDK。execute()、executeStream()、executeBackground() 会把 timeoutMs 转成 OpenSandbox SDK 的 timeoutSeconds。限制:
修改点:
packages/service/core/ai/sandbox/runtime/profile/opensandbox.tspackages/service/test/core/ai/sandbox/provider/config.test.ts当前策略:
defaultAction: 'allow'
deny: localhost, host.docker.internal, host.orb.internal, docker.orb.internal, gateway.orb.internal, proxyproxy.orb.internal, *.orb.internal, *.orb.local
效果:
限制:
sdk/sandbox-adapter,由 FastGPT runtime profile 显式启用,不让 SDK adapter 对所有使用方无条件注入。修改点:
packages/service/core/ai/sandbox/toolCall/shell.tool.tspackages/service/test/core/ai/sandbox/toolCall/shell.tool.test.tssdk/sandbox-adapter/src/adapters/OpenSandboxAdapter/index.tssdk/sandbox-adapter/tests/unit/adapters/OpenSandboxAdapter.test.tssdk/sandbox-adapter/tests/integration/OpenSandbox.test.ts效果:
timeout 只能是 1 到 600 秒。timeoutSeconds。sleep 10 在 1 秒 timeout 下被终止。限制:
修改点:
projects/agent-sandbox/Dockerfileprojects/agent-sandbox/entrypoint.shsdk/sandbox-adapter/tests/integration/OpenSandbox.test.ts效果:
10001 的 sandbox 用户。/home/sandbox 和 /workspace 归 sandbox 所有。USER sandbox。FASTGPT_SESSION_ID、FASTGPT_WORKDIR。限制:
修改点:
sdk/sandbox-adapter/src/constants.tssdk/sandbox-adapter/src/index.tssdk/sandbox-adapter/src/adapters/OpenSandboxAdapter/index.tspackages/service/core/ai/sandbox/runtime/profile/opensandbox.tspackages/service/core/ai/sandbox/volume/config.tspackages/service/core/ai/sandbox/volume/service.tsdocument/content/self-host/config/env.mdxdocument/content/self-host/config/env.en.mdx效果:
OPEN_SANDBOX_DEFAULT_ROOT_PATH = '/workspace' 作为唯一默认根路径。workDirectory 使用 SDK 导出的默认根路径。rootPath fallback 也使用同一个默认根路径。AGENT_SANDBOX_VOLUME_MANAGER_MOUNT_PATH 环境变量,避免部署配置和镜像契约不一致。限制:
/workspace 是一致性和误配置收敛,不是安全边界。/home/sandbox 仍是用户 home 和 entrypoint 所在目录,不作为持久化工作区。结论:
/tmp、语言工具链输出、调试产物等合法场景。原因:
execute(),攻击者就可以通过 shell、Python、Node 等读取容器内可见路径。cat /etc/passwd 这类命令执行路径。真正边界:
已通过的测试:
pnpm -C packages/service exec vitest run test/core/ai/sandbox/runtime/profile.test.ts test/core/ai/sandbox/volume/config.test.ts test/core/ai/sandbox/volume/service.test.ts test/core/ai/sandbox/provider/config.test.ts
pnpm -C sdk/sandbox-adapter exec vitest run tests/unit/adapters/BaseSandboxAdapter.test.ts tests/unit/adapters/OpenSandboxAdapter.test.ts
pnpm -C sdk/sandbox-adapter build
docker build -t fastgpt-agent-sandbox:codex-security-test projects/agent-sandbox
docker run --rm --entrypoint bash fastgpt-agent-sandbox:codex-security-test -lc 'test "$(id -u)" != "0" && test "$(id -un)" = "sandbox" && test -w /home/sandbox && test -w /workspace'
OPENSANDBOX_BASE_URL=http://127.0.0.1:8090 \
OPENSANDBOX_API_KEY=<redacted> \
OPENSANDBOX_RUNTIME=docker \
OPENSANDBOX_IMAGE_REPOSITORY=fastgpt-agent-sandbox \
OPENSANDBOX_IMAGE_TAG=codex-security-test \
OPENSANDBOX_INTEGRATION_CONTAINER_SECURITY=true \
OPENSANDBOX_INTEGRATION_RESOURCE_LIMITS=true \
OPENSANDBOX_INTEGRATION_NETWORK_ISOLATION=true \
pnpm -C sdk/sandbox-adapter exec vitest run tests/integration/OpenSandbox.test.ts -t "Security Runtime Tests"
真实集成测试已验证:
当前不应运行或不应视为通过的测试:
packages/service/test/core/ai/sandbox/deploySecurity.test.ts原因:
现状:
SANDBOX_API_KEY。[server].api_key。network_mode 改为 bridge。dns+nft。风险:
建议:
node deploy/init.mjs,并确保 deploy/docker 与 document/public/deploy/docker 同步。现状:
/var/run/docker.sock 创建和管理 sandbox。风险:
建议:
现状:
:ro,这也不是 Docker API 权限边界。风险:
建议:
VM_AUTH_TOKEN。:ro 只当作文件挂载卫生措施,不要当作安全隔离。现状:
风险:
10.0.0.0/8、172.16.0.0/12、192.168.0.0/16、link-local、metadata IP,单靠 FQDN deny 不能完整禁止。建议:
现状:
OPEN_SANDBOX_DOCKER_LOCAL_NETWORK_POLICY 目前在 FastGPT service runtime profile。风险:
建议:
sdk/sandbox-adapter 导出默认策略或 factory。现状:
.mdx 文档仍描述 OpenSandbox API key 必填。风险:
建议:
.mdx,说明需要手动配置 OpenSandbox server api_key。现状:
风险:
建议:
现状:
projects/agent-sandbox/Dockerfile 通过 NodeSource 和 Bun 外部安装脚本安装运行时。风险:
建议:
现状:
风险:
建议:
等确认可以恢复 YAML 安全部署后,建议一次性落地以下配置:
export SANDBOX_API_KEY="$(openssl rand -hex 32)"
AGENT_SANDBOX_OPENSANDBOX_API_KEY: ${SANDBOX_API_KEY:?Set SANDBOX_API_KEY before docker compose up}
[server]
api_key = "${SANDBOX_API_KEY:?Set SANDBOX_API_KEY before docker compose up}"
[docker]
network_mode = "bridge"
drop_capabilities = ["AUDIT_WRITE", "MKNOD", "NET_ADMIN", "NET_RAW", "SYS_ADMIN", "SYS_MODULE", "SYS_PTRACE", "SYS_TIME", "SYS_TTY_CONFIG"]
no_new_privileges = true
pids_limit = 512
[egress]
mode = "dns+nft"
opensandbox-server:
mem_limit: 1g
cpus: '1.0'
pids_limit: 512
fastgpt-volume-manager:
mem_limit: 512m
cpus: '0.5'
pids_limit: 256
ports:
- 127.0.0.1:8090:8090
- 127.0.0.1:3005:3000
docker build -t <registry>/fastgpt-agent-sandbox:<tag> projects/agent-sandbox
docker push <registry>/fastgpt-agent-sandbox:<tag>
cd deploy
node init.mjs
SANDBOX_API_KEY=test-key docker compose -f deploy/docker/cn/docker-compose.pg.yml config --quiet
pnpm -C packages/service exec vitest run test/core/ai/sandbox/deploySecurity.test.ts
真实 OpenSandbox Docker 安全集成验证:
OPENSANDBOX_BASE_URL=<opensandbox-url> \
OPENSANDBOX_API_KEY=<sandbox-api-key> \
OPENSANDBOX_RUNTIME=docker \
OPENSANDBOX_IMAGE_REPOSITORY=<agent-sandbox-image-repo> \
OPENSANDBOX_IMAGE_TAG=<agent-sandbox-image-tag> \
OPENSANDBOX_INTEGRATION_CONTAINER_SECURITY=true \
OPENSANDBOX_INTEGRATION_RESOURCE_LIMITS=true \
OPENSANDBOX_INTEGRATION_NETWORK_ISOLATION=true \
pnpm -C sdk/sandbox-adapter exec vitest run tests/integration/OpenSandbox.test.ts -t "Security Runtime Tests"