agent-Specialization/modules/docker_readonly_exec.py
JOJO 8257e4d34d feat(security): 沙箱只读真强制与权限模式边界收敛
- docker:只读/审批档 run_command、后台命令与持久终端改用非特权 uid(10001) 执行角色,内核 DAC 强制只读,取代文本特征识别;Dockerfile 加固(agent 用户 / git safe.directory / 去 setuid)
- macOS:只读与可写沙箱 profile 统一为白名单读模型(deny default + 系统目录/工作区/路径授权),修复 deny 顺序导致的工作区 .env 实际可读漏洞;可写 profile 白名单化后审批不再放大读取,越界读取唯一途径为路径授权
- 权限模式:受限档(readonly/approval/auto_approval)与 direct 执行环境硬互斥——进入受限档压回沙箱并记录,切回 unrestricted 恢复,存量受限+direct 对话加载自愈矫正
- 配置:路径授权来源收敛为 host_sandbox_policy.json + 环境变量两个通道(移除 settings.json 映射)
- 修复:新建对话权限模式被个性化默认值覆盖、/new 切只读后回落无限制的继承 bug
- 原生文件工具读边界与沙箱白名单同源对齐
2026-08-30 22:07:14 +08:00

57 lines
2.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""docker 容器内只读执行非特权执行角色uid/gid
设计2026-08-30 云端实测验证,详见项目记忆 sandbox_readonly_reform_research
- 容器主进程与可写执行保持 rootsandbox_write_access=False 的执行通道
run_command 前台/后台、只读语境下创建的持久终端)统一改用非特权 uid
(默认 10001:10001可用环境变量覆盖
- 强制力来自内核 DAC工作区 bind 挂载的文件属主是宿主机 root非属主且
无 o+w → 写/删/chmod/umount 一律 EACCES/EPERM600 权限的 .env 等敏感
文件天然不可读。此前的「命令文本特征识别」降级为审批决策的启发式,
不再是 docker 只读的安全边界。
- 不依赖镜像中存在该用户(数字 uid 直接生效),旧镜像直接受益;
docker/terminal.Dockerfile 同步创建 agent 用户与 git safe.directory
供未来构建的镜像使用。
- 逃逸门槛需要先提权setuid 漏洞/内核漏洞),远高于嵌套 namespace
方案的 umount 逃逸;云端默认 seccomp 会拦 unshare(CLONE_NEWUSER)
嵌套方案已被本方案取代。
- 已知边界macOS Docker Desktop 的 virtiofsfakeowner不按 uid 执行
权限检查,本机制仅在 Linux 宿主机(云端/ Linux 桌面)生效,属预期差异;
持久终端在 approval/auto_approval 模式下同为只读身份,写入命令请走
run_command审批通过后以 root 重跑)。
"""
from __future__ import annotations
import os
from typing import List, Tuple
def docker_readonly_uid_gid() -> Tuple[str, str]:
"""只读执行身份的 uid/gid默认 10001:10001环境变量可覆盖
选取原则:避开宿主机工作区文件属主 uid否则会被 DAC 认成主人而放行),
10001 为冷门值;如部署环境文件属主恰为该值,用环境变量改。
"""
uid = os.environ.get("DOCKER_READONLY_EXEC_UID", "10001").strip() or "10001"
gid = os.environ.get("DOCKER_READONLY_EXEC_GID", uid).strip() or uid
return uid, gid
def docker_readonly_exec_args() -> List[str]:
"""构造只读执行的 docker exec 前缀参数(紧跟在 "exec" 之后)。
含:
- ``-u uid:gid``:非特权执行身份(内核 DAC 强制只读的核心);
- ``HOME=/tmp``uid 在 /etc/passwd 无条目时提供可写 HOME
- git safe.directory 修复:工作区属主是 root非属主 git 会报
"detected dubious ownership",用 env 方式注入,不依赖镜像内 gitconfig。
"""
uid, gid = docker_readonly_uid_gid()
return [
"-u", f"{uid}:{gid}",
"-e", "HOME=/tmp",
"-e", "GIT_CONFIG_COUNT=1",
"-e", "GIT_CONFIG_KEY_0=safe.directory",
"-e", "GIT_CONFIG_VALUE_0=*",
]