0022-managed-skill-dirs-readable-in-sandbox.md 2.3 KB

ADR-0022 服务管理的技能目录在沙箱中只读可见;Codex 的禁止规则绕开可读路径

  • 状态:Accepted · 日期:2026-10-25 · 补充 ADR-0010、ADR-0017

背景

实施自定义技能时发现两个问题,也影响已有的第三方技能:

  1. 内置全局禁止项包含 {dataDir}/data(数据库、版本库、MCP 数据都在这里),而第三方技能与自定义技能的生效目录 data/community-skills、data/custom-skills 也在其中。
    • Claude 的 Read 等工具经过 checkAccess,全局禁止项优先于可读路径,所以读不到技能的参考文档。
    • Codex 的沙箱同样禁止。
    • SKILL.md 本身由引擎进程读取,所以技能看起来"能触发",但参考文档和脚本用不了。
  2. 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)、数据库等仍不可见