- 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 - 原生文件工具读边界与沙箱白名单同源对齐
57 lines
2.8 KiB
Python
57 lines
2.8 KiB
Python
"""docker 容器内只读执行:非特权执行角色(uid/gid)。
|
||
|
||
设计(2026-08-30 云端实测验证,详见项目记忆 sandbox_readonly_reform_research):
|
||
|
||
- 容器主进程与可写执行保持 root;sandbox_write_access=False 的执行通道
|
||
(run_command 前台/后台、只读语境下创建的持久终端)统一改用非特权 uid
|
||
(默认 10001:10001,可用环境变量覆盖)。
|
||
- 强制力来自内核 DAC:工作区 bind 挂载的文件属主是宿主机 root,非属主且
|
||
无 o+w → 写/删/chmod/umount 一律 EACCES/EPERM;600 权限的 .env 等敏感
|
||
文件天然不可读。此前的「命令文本特征识别」降级为审批决策的启发式,
|
||
不再是 docker 只读的安全边界。
|
||
- 不依赖镜像中存在该用户(数字 uid 直接生效),旧镜像直接受益;
|
||
docker/terminal.Dockerfile 同步创建 agent 用户与 git safe.directory,
|
||
供未来构建的镜像使用。
|
||
- 逃逸门槛:需要先提权(setuid 漏洞/内核漏洞),远高于嵌套 namespace
|
||
方案的 umount 逃逸;云端默认 seccomp 会拦 unshare(CLONE_NEWUSER),
|
||
嵌套方案已被本方案取代。
|
||
- 已知边界:macOS Docker Desktop 的 virtiofs(fakeowner)不按 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=*",
|
||
]
|