ADR-0022 服务管理的技能目录在沙箱中只读可见;Codex 的禁止规则绕开可读路径
- 状态:Accepted · 日期:2026-10-25 · 补充 ADR-0010、ADR-0017
背景
实施自定义技能时发现两个问题,也影响已有的第三方技能:
- 内置全局禁止项包含
{dataDir}/data(数据库、版本库、MCP 数据都在这里),而第三方技能与自定义技能的生效目录 data/community-skills、data/custom-skills 也在其中。
- Claude 的 Read 等工具经过
checkAccess,全局禁止项优先于可读路径,所以读不到技能的参考文档。
- Codex 的沙箱同样禁止。
- SKILL.md 本身由引擎进程读取,所以技能看起来"能触发",但参考文档和脚本用不了。
- Codex(0.164)的文件权限中,父目录为 deny 时子路径的 read 无效,write 有效。已实测:父 deny + 子 read,读取被拒;父 deny + 子 write,写入正常。
- 因此宽松模式下
softDeny 中的服务目录(/srv/agent-server)会让 Codex 读不到其中的本地技能目录、Python 运行环境与官方技能目录。
- 当前工作区可写,不受影响。
决策
checkAccess 对服务管理的技能目录(managedSkillRoots():第三方、自定义技能的生效目录)只放行读取,并且先于全局禁止项判断。data 下的其他内容仍然禁止,写入仍然禁止。
- Claude 的 Bash 沙箱:
denyRead 中的 data 目录与 allowRead 中的技能目录同时存在时,更具体的 allowRead 生效(已实测)。无需改动。
- Codex 的权限表:要禁止的目录(全局禁止项、宽松模式的 softDeny)如果包含必须可读的路径(表中所有 read 项),不再禁止该目录本身,而是逐层展开,逐个禁止通往可读路径以外的其他条目(
denyAround)。
- 已在生产 Codex 上验证:可读路径能读、不能写,同级条目被拒。
- 展开在每次对话时计算。之后新出现的条目要到下一次对话才被禁止;这些目录只由服务写入。
后果
- 第三方技能与自定义技能的参考文档、脚本、模版在两个引擎中都可用
- 宽松模式下 Codex 可以使用本地技能目录与 Python 运行环境
- 自定义技能的版本库(
data/custom-skill-store)、数据库等仍不可见