AI 编码 agent 的安全模型,正在长得越来越像 K8s 的 PSP
一份配置文件,比一个产品发布更值得读
2026 年 5 月 8 日,OpenAI 在自己 blog 上挂出 Running Codex safely at OpenAI。没有 demo,没有 benchmark,只有一份 config.toml 加一份 requirements.toml 的真实片段。
这份文档的核心价值在于:它把 coding agent 的安全边界抽象成了五个可配置接口。
接口长这样——五个槽位:
- Sandbox:agent 在哪写、读什么、能不能碰网络
- Approval:什么动作放行,什么动作停下来等人
- Network:出站流量的白/黑名单
- Credential:登录凭据怎么存
- Rules:哪些 shell 命令默认允许,哪些必须拦
这五个槽位不是 Codex 独有。它对任何 coding agent 都成立——Claude Code、Cursor、Cline、Aider,都得在这五件事上给出答案。
我打开手边的 Claude Code,按这五个槽位逐一对照了一遍。结论先放出来:
<figure><img src=“images/01-5-slot-table.png” alt=“01-5-slot-table”></figure>
这不是新问题,K8s 已经走过一遍
Kubernetes 的老用户对这一套应该不陌生。
早期 K8s 没有 PodSecurityPolicy。Pod 想用 host network 就用,想 mount /etc 就 mount,权限模型一片混乱。直到社区把"特权、capabilities、host 资源、用户、文件系统"几个维度抽象出来变成统一策略接口,所有 Pod 才被同一套尺子框住。
AI coding agent 现在走的就是这条老路。一年前大家比的是"哪家模型写代码更聪明",OpenAI 这份文档已经把焦点从"模型聪不聪明"挪到了"它跑起来时的边界"。谁先把这些维度摆清楚,谁就更有机会影响后面的行业默认接口。
这其实是一份判断 AI coding agent 能不能进 production 流程的检查清单。
五个槽位,Claude Code 各填到哪一格
Sandbox:Claude Code 也补上了
OpenAI 写的是:
sandbox_workspace_write.writable_roots = ["~/development"]
allowed_sandbox_modes = ["read-only", "workspace-write"]
意思是 Codex 默认在 sandbox 里跑,只能写 ~/development。
Claude Code 现在也有原生 sandbox。对应的不是 allowed_sandbox_modes,而是 sandbox.enabled 加 sandbox.filesystem.*:
{
"sandbox": {
"enabled": true,
"failIfUnavailable": true,
"filesystem": {
"denyRead": ["~/"],
"allowRead": ["."],
"allowWrite": [".", "/tmp/build"]
}
}
}
这里要分清两层:permissions 决定 Claude 能不能调用某个工具;sandbox 决定 Bash 和它拉起的子进程能碰哪些文件、哪些网络。前者是审批层,后者是 OS 级围栏。
Approval:不同实现,效果接近
OpenAI 跑了一个 auto-review subagent,每个 action 把"planned action + recent context"打包发给它,subagent 判断要不要放行。
Claude Code 不走 LLM 二审。它有两件武器:
permissions.allow里穷举静态白名单PreToolUsehook 跑自己的脚本判定
前者快,缺点是规则要自己维护;后者灵活,缺点是写脚本要花心思。对绝大多数开发者,静态白名单加 ~20 条命令够用——auto-review 的 LLM 二审更适合企业场景。
五个槽位都填上了,只是具体实现思路不同。
Network:也有了,但前提是开 sandbox
OpenAI 给的是 domain 级控制:
[experimental_network]
enabled = true
denied_domains = ["pastebin.com"]
allowed_domains = ["login.microsoftonline.com", "*.openai.com"]
Claude Code 的对应项在 sandbox.network:
{
"sandbox": {
"enabled": true,
"network": {
"allowedDomains": ["github.com", "registry.npmjs.org"],
"deniedDomains": ["pastebin.com"],
"allowManagedDomainsOnly": true
}
}
}
这和 WebFetch(domain:...) 不是一回事。WebFetch 规则只管 WebFetch 工具;sandbox network 才会约束 Bash 里跑出来的 curl、npm、git。如果没开 sandbox,再漂亮的 WebFetch deny 都挡不住子进程出网。
Credential:不是统一缺口,是平台差异
OpenAI 把 CLI 和 MCP 凭据都塞进 OS keyring:
cli_auth_credentials_store = "keyring"
mcp_oauth_credentials_store = "keyring"
Claude Code 这里不能再一句话说成"平文件落盘"。官方文档里的规则是:
- macOS:加密的 macOS Keychain
- Linux:
~/.claude/.credentials.json,文件 mode0600 - Windows:用户目录下的
.credentials.json,继承用户 profile ACL - 如果 Linux/Windows 设置了
CLAUDE_CONFIG_DIR,凭据文件会挪到那个目录下
所以真正要检查的是 Linux/Windows/自定义配置目录场景:
stat -c "%a %n" ~/.claude/.credentials.json 2>/dev/null
chmod 600 ~/.claude/.credentials.json 2>/dev/null
这不是说 Claude Code 在凭据上天然更弱,而是团队落地时要把"凭据实际在哪、权限是不是收紧、CI 有没有用长期 token"列进检查表。
Rules:照抄
最后这段最干净。OpenAI 用 Python 语法写 prefix rule:
prefix_rule(pattern=["gh", "pr", ["view", "list"]], decision="allow")
Claude Code 直接对应到 JSON 的 permissions.allow / deny。配置语法不是重点,真正可复用的是这五个安全槽位。Rules 这一格最接近一比一翻译,下面就是。
今晚就能动手的三段配置
以下是基于这五个槽位整理出来的 settings.json 落地实践。
1. sandbox 文件和网络边界(对应 Sandbox + Network)
{
"sandbox": {
"enabled": true,
"failIfUnavailable": true,
"filesystem": {
"denyRead": ["~/"],
"allowRead": ["."],
"allowWrite": [".", "/tmp/build"]
},
"network": {
"allowedDomains": ["github.com", "registry.npmjs.org"],
"deniedDomains": ["pastebin.com"],
"allowManagedDomainsOnly": true
}
}
}
这段是最该先抄的。它给 Bash 和子进程画边界,解决的不是"Claude 会不会点错工具",而是"工具跑起来以后最多能碰到哪"。
2. permissions 白/黑名单(对应 Rules + 部分 Approval)
{
"permissions": {
"allow": [
"Bash(gh pr view:*)",
"Bash(gh pr list:*)",
"Bash(git status:*)",
"Bash(git diff:*)",
"Bash(git log:*)",
"Bash(npm test:*)",
"Bash(ls:*)",
"Bash(cat:*)"
],
"deny": [
"Bash(rm -rf:*)",
"Bash(git push --force:*)",
"Bash(psql:*production*)",
"WebFetch(domain:pastebin.com)"
]
}
}
写在 ~/.claude/settings.json。allow 列日常无害命令,deny 列高危动作或不可逆命令。
3. 凭据和危险动作兜底(对应 Credential + Approval)
stat -c "%a %n" ~/.claude/.credentials.json 2>/dev/null
chmod 600 ~/.claude/.credentials.json 2>/dev/null
macOS 用户看到这里不用去找 .credentials.json,重点是 Keychain 和环境变量;Linux/Windows 用户重点看文件权限和 CLAUDE_CONFIG_DIR。
在项目 .claude/settings.json 里:
"hooks": {
"PreToolUse": [
{"matcher": "Bash", "hooks": [{"type":"command","command":"./scripts/dangerous-cmd-gate.sh"}]}
]
}
脚本里自己写判断逻辑——检测到 kubectl delete 直接 exit 1。是规则审不是 LLM 审,但拦住灾难够用。
安全模型正在变成准入门槛
OpenAI 这份文档真正值钱的不是配置语法——抄到 config.toml 也跑不起 Codex。值钱的是它把 AI coding agent 安全模型拆成五个槽位:sandbox、approval、network、credential、rules。
这五个槽位对你手上每一个 AI 编程工具都成立。今晚打开它的配置文件,把这五件事过一遍:
- 让它写哪些目录?
- 危险动作怎么停?
- 流量怎么管?
- 凭据塞在哪?
- 哪些命令默认允许?
每一格都能给出可解释的答案——它可以进 production。有一格答不出来——别让它跑你不愿意丢的代码。
K8s 当年也是这样从"Pod 想跑啥跑啥"走到 PSP 的。AI coding agent 这一波,五个槽位就是它的 PSP。