主流 Agent 入门教程 / Codex
8. 权限沙箱与安全边界
原文备份 · 第 9 / 27 篇 · 查看极客时间原知识库 ↗
本篇目录 · 16 节
来源:Codex
本课按能力区分调查 read-only 与实施 workspace-write。若 /permissions 未显示只读,退出后用
codex --sandbox read-only --ask-for-approval on-request启动;写入前明确切换 workspace-write 并提供计划。以实际权限摘要为准。
预计阅读时间:45 分钟
本篇目标:通过给 TaskFlow 增加 CSV 导入,理解沙箱、审批和权限范围的区别,并学会判断一次授权是否合理。
Codex 与普通聊天工具最明显的不同,是它不只给建议,还可以读文件、改代码和运行命令。因此,一个任务除了要说清“要做什么”,还要说清“允许在哪里做、可以使用什么资源”。
这一篇不会用故意危险的命令测试安全性。我们会用一个正常需要读写文件、却完全不需要联网的功能,观察 Codex 如何在边界内工作。
一、先分清沙箱和审批
可以把它们理解成两个不同的问题:
- 沙箱回答“Codex 当前可以自主访问哪些文件和资源”;
- 审批策略回答“当操作需要越过边界时,Codex 是否会停下来请求批准”。
官方文档列出的常见沙箱模式包括:
| 模式 | 能做什么 | 适合场景 |
|---|---|---|
read-only |
主要用于检查文件,不在工作区写入 | 读代码、解释项目、做只读审查 |
workspace-write |
可以在工作区内读写文件并运行常规本地命令 | 日常开发、测试、文档修改 |
danger-full-access |
取消沙箱的文件系统和网络边界 | 只在你确实愿意提供完整访问时使用 |
常见审批策略中,on-request 表示 Codex 先在沙箱内工作,必须越界时再请求审批;never 则表示不会停下来向用户发起审批。never 不等于自动获得更多权限:沙箱边界仍然由当前配置决定。
官方文档:Sandbox。
二、先检查权限,再开始写功能
在 TaskFlow 目录中启动:
codex --sandbox workspace-write --ask-for-approval on-request
进入交互界面后输入:
/permissions
当前版本会打开权限选择器。本篇需要修改 TaskFlow 项目内的代码、测试和样例文件,因此不能继续使用只读沙箱。
在你当前看到的三个选项中,应该选择 Ask for approval。它对应本篇启动命令中的 workspace-write 加 on-request:Codex 可以在 TaskFlow 工作区内修改文件和运行常规命令,越过边界时则由你决定是否批准。
另外两个选项不是本篇默认值:
- Approve for me 仍保留工作区边界,但把越界请求交给自动审查;
- Full access 会放开文件系统和网络边界,本篇完全不需要。
本篇不需要:
- 读取桌面、下载目录或其他项目;
- 安装第三方依赖;
- 访问公网;
- 读取
.env、SSH 密钥或云服务凭据; - 使用 Full Access。
先写出“不需要什么”很有用。如果之后出现与这些范围冲突的申请,你就知道应该先停下来问为什么。
三、先定义 CSV 导入的行为
这一节只定义功能,还没有开始创建文件或修改代码。此时项目中还不 存在 samples/ 目录和 samples/tasks.csv文件,所以下面的命令暂时不要执行。
我们希望新增的命令用法是:
python3 taskflow.py --data <任务数据文件> import-csv <CSV 文件>
例如,功能完成后,可以让它读取:
samples/tasks.csv
本篇使用的 samples/tasks.csv 是一份固定的练习文件。它的完整内容如下:
title,completed
整理会议纪要,false
提交报销,true
准备周报,false
其中:
- 第一行是表头;
- 后面三行是准备导入的三条任务;
false表示未完成;true表示已完成。
这份文件将在第五节创建。现在不需要现在手动创建,也不要现在运行导入命令,我们在这里只需要先确定导入规则:
- CSV 必须包含
title和completed两列; title去掉首尾空格后不能为空;completed只接受true或false;- 只读取命令参数指定的 CSV 文件;
- 新任务追加到现有列表,不覆盖旧数据;
- 任意一行不合法时,整次导入失败,原数据保持不变;
- 本版不做重复任务去重,重复导入会照实追加,并在 README 中说明。
四、让 Codex 先解释权限需求
输入:
我要为 TaskFlow 增加 import-csv 命令。
请先检查现有代码、数据保存方式和测试,给出实现计划,暂时不修改文件。
功能规则:
1. CSV 必须包含 title 和 completed 两列;
2. title 去掉首尾空格后不能为空;
3. completed 只接受 true 或 false;
4. 只读取命令参数指定的 CSV 文件;
5. 新任务追加到现有列表,不覆盖旧数据;
6. 任意一行不合法时,整次导入失败,原数据保持不变;
7. 本版不做重复任务去重,重复导入会照实追加,并在 README 中说明。
安全边界:
1. 只读取命令参数明确指定的 CSV;
2. 测试使用临时目录,不触碰真实 data/tasks.json;
3. 不访问网络,不安装依赖;
4. 不读取工作区外的文件;
5. 导入失败时不能留下部分写入。
请在计划中单独说明:本任务需要读取和写入哪些路径,为什么 workspace-write 已经足够。
理想的权限说明应该很简单:
需要读:taskflow.py、tests/、README.md、用户指定的 CSV
需要写:taskflow.py、tests/、README.md、samples/tasks.csv
不需要:网络、第三方依赖、工作区外目录
如果它声称需要 Full Access,让它指出哪一个具体步骤无法在当前工作区中完成。对这个功能来说,通常没有充分理由扩大权限。
五、先在工作区内准备样例
确认计划后,把下面的完整任务交给 Codex:
请先完成下面的准备工作:
1. 如果 samples 目录不存在,就创建它;
2. 创建 samples/tasks.csv;
3. 文件内容必须严格如下:
title,completed
整理会议纪要,false
提交报销,true
准备周报,false
创建后重新读取这个文件,确认表头和三行数据正确。
然后按照已经确认的计划实现 import-csv,补充自动测试并更新 README。完成后先运行导入功能的测试,再运行完整测试。
测试必须使用临时任务数据,不能读写真实的 data/tasks.json。不要申请网络权限,也不要访问工作区外的文件。
创建完成后,学员可以亲自检查文件。
macOS、Linux 或 WSL2:
!cat samples/tasks.csv
Windows PowerShell:
!Get-Content samples\tasks.csv
看到完整的表头和三行任务后,才能确认样例已经准备好。
实际测试导入功能时,也不要直接运行:
python3 taskflow.py import-csv samples/tasks.csv
因为这可能写入默认的真实数据文件。应让 Codex通过 --data 明确指定临时的 tasks.json,例如:
请在系统临时目录中创建一份独立的 tasks.json,然后执行完整 CLI:
python3 taskflow.py --data <临时tasks.json路径> import-csv samples/tasks.csv
不要读取或修改项目中的 data/tasks.json。执行后报告退出码、导入数量和临时数据文件内容。
这一步的关键不是一定要用 samples/。关键是第一次练习时,样例、代码和测试都留在一个可检查的项目边界中。
如果真实 CSV 位于工作区之外,对初学者来说,最容易检查的方法是先复制一份脱敏副本到项目的 imports/ 目录。如果确实需要使用额外目录,应当只增加那一个明确路径,并先用当前版本的 codex --help 确认命令行选项,不要为了一个文件开放整个主目录。
六、看到审批时,具体看什么
审批弹窗的外观可能随版本变化,但判断方法基本不变。
先看操作
它是要读文件、写文件、运行测试、联网,还是执行删除、发布等会改变外部状态的操作?
再看对象
目标路径或网络地址是什么?它是否与当前任务直接相关?
再看范围
这次授权只针对当前操作,还是会对后续一类命令持续生效?能批准单次操作,就不要因为方便而扩大成宽泛规则。
最后看是否必要
可以在工作区内完成的任务,为什么要读取其他目录?可以用标准库完成的功能,为什么要下载依赖?
对本篇任务来说,下列操作一般符合预期:
- 在 TaskFlow 项目中创建样例和测试;
- 修改
taskflow.py和 README; - 运行
unittest; - 读取你明确放入项目的 CSV;
- 查看 Git Diff。
下列情况则应该先拒绝或暂停确认:
- 读取无关项目、SSH 目录、钥匙串或云凭据;
- 将 CSV 发送到外部服务;
- 下载一个本任务根本不需要的依赖;
- 覆盖或删除真实任务数据;
- 没有具体理由地切换到
danger-full-access。
七、验证正常导入,也验证失败时不写一半
完成后先运行完整测试。
macOS、Linux 或 WSL2:
!python3 -m unittest
# 二选一,选择适用于当前系统的命令
!python3 -m unittest discover -s tests -v
Windows:
!py -m unittest
# 二选一,选择适用于当前系统的命令
!py -m unittest discover -s tests -v
然后让 Codex 在临时目录中实跑下列场景:
| 场景 | 期望结果 |
|---|---|
| 三行合法数据 | 成功导入 3 条,退出码为 0 |
缺少 title 列 |
提示缺少必需列,退出码非 0,旧数据不变 |
| 某行标题为空 | 指出错误行或有用的定位信息,整次不写入 |
completed 为 yes |
按当前规则拒绝,不悄悄猜测 |
| 数据写入前校验失败 | 现有任务数量和内容完全不变 |
| 重复导入同一文件 | 行为与 README 中约定一致 |
输入:
请在临时目录中验证上述六个场景。每个场景列出输入文件的关键内容、运行命令、退出码、关键输出,以及导入前后的任务数量。不要读写真实 data/tasks.json。
正常导入的输出可能类似:
已导入 3 条任务。
非法布尔值则可能类似:
错误:第 4 行 completed 必须是 true 或 false。
文字不必与示例相同,重点是用户能找到问题,失败后数据仍然完整。
八、用 Diff 检查代码范围和数据风险
输入:
/diff
这次不只看“功能能不能跑”,还要看:
- 是否引入了本来不需要的第三方库;
- 是否写死了某台电脑的绝对路径;
- 是否一边读 CSV 一边直接写正式数据,导致中途失败时留下半成品;
- 错误信息是否泄露了不必要的完整文件内容;
- 测试是否使用临时目录;
- 是否把真实 CSV 或运行后的
tasks.json加入了 Git。
再做一次只读审查:
请只从权限与数据完整性角度审查当前 Diff,不要修改:
- 文件读取范围是否过大;
- 输入是否在写入前完整校验;
- 失败是否可能留下部分写入;
- 日志或错误信息是否泄露文件内容;
- 新增权限是否都与功能直接相关。
每个发现给出文件位置和触发条件。
确认后再通过 git 提交实际变更的文件。
九、把这一阶段提交到 Git
测试、手工验证和 Diff 都通过后,打开另一个终端,进入 TaskFlow 项目根目录。先查看实际改动:
git status --short
确认列表中只有本篇产生的代码、测试、文档和样例文件,再明确暂存它们:
git add taskflow.py tests README.md samples/tasks.csv
如果 Codex 实际还修改了其他必要文件,不要直接使用 git add .。先确认它确实属于 CSV 导入功能,再把准确路径补到 git add 命令中。
提交前检查暂存区:
git diff --cached --check
git diff --cached
前一条正常情况下没有输出;后一条应只包含已经审查过的 CSV 导入改动。确认无误后提交:
git commit -m "feat: add CSV import"
git status --short
提交成功时会看到提交摘要;最后一条命令应当没有输出。若仍列出文件,先判断它们是遗漏的本篇改动,还是不应提交的运行数据。data/tasks.json 等真实数据不应被顺手加入版本库。
十、为什么“一直批准”和“什么都拒绝”都不理想
如果每次看到审批都直接允许,审批就失去了意义。反过来,如果任何写入和测试都拒绝,Codex 又无法完成开发任务。
更实用的方法是:事先界定工作区和允许的操作,边界内的常规工作让 Codex 连续执行,越界时再检查具体原因。沙箱的价值之一,就是减少无意义的反复确认,同时保留清楚的信任边界。
十一、一份可复用的权限任务模板
请完成:<任务目标>
允许的范围:
- 可读取:<必要的目录或文件>
- 可写入:<必要的目录或文件>
- 可运行:<测试、构建或检查命令>
本任务不需要:
- <网络、安装依赖、工作区外文件等>
安全要求:
- 先读取和验证,再写入;
- 失败时不能留下部分结果;
- 删除、覆盖、发布和外部发送前先停下来说明;
- 需要扩大权限时,说明具体操作、目标和不可替代性。
完成后报告实际读写范围、运行命令、验证结果和未执行的高风险操作。
本篇小结
沙箱决定 Codex 在什么边界内能自主行动,审批策略决定它越过边界时怎样停下来。判断一次授权时,不要只看“Codex 说需要”,要看操作、对象、范围和必要性。
本篇完成的 CSV 导入只需要工作区内的读写和本地测试。权限越贴合任务,执行过程越容易检查。
下一篇,我们会把标准库、临时目录、数据保护和完整测试等约束写进 AGENTS.md,让新会话也能自动了解项目的工作方式。