← 随机比特 / 所有内容

AI 编码 agent 的安全模型,正在长得越来越像 K8s 的 PSP

2026-05-12 · 随机比特
AI 编码 agent 的安全模型,正在长得越来越像 K8s 的 PSP

AI 编码 agent 的安全模型,正在长得越来越像 K8s 的 PSP

一份配置文件,比一个产品发布更值得读

2026 年 5 月 8 日,OpenAI 在自己 blog 上挂出 Running Codex safely at OpenAI。没有 demo,没有 benchmark,只有一份 config.toml 加一份 requirements.toml 的真实片段。

这份文档的核心价值在于:它把 coding agent 的安全边界抽象成了五个可配置接口

接口长这样——五个槽位:

这五个槽位不是 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.enabledsandbox.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 二审。它有两件武器:

前者快,缺点是规则要自己维护;后者灵活,缺点是写脚本要花心思。对绝大多数开发者,静态白名单加 ~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 里跑出来的 curlnpmgit。如果没开 sandbox,再漂亮的 WebFetch deny 都挡不住子进程出网。

Credential:不是统一缺口,是平台差异

OpenAI 把 CLI 和 MCP 凭据都塞进 OS keyring:

cli_auth_credentials_store = "keyring"
mcp_oauth_credentials_store = "keyring"

Claude Code 这里不能再一句话说成"平文件落盘"。官方文档里的规则是:

所以真正要检查的是 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。