Codex Skill 里不应该明文保存密钥
这次用 Figma Personal Access Token 调用 Figma REST Images API,把设计节点导成 PNG。把 token 放进 Skill,后续每次执行都不用再问,看起来很省事。
但这类值不应该写进 Skill。Skill 是可复用的长期指令,密钥是会过期、会泄露、需要轮换的私有凭据。把两者混在一起,短期方便,长期会把风险带进仓库、备份、日志、Agent 上下文和后续迁移里。
我把凭据留在本机私有 env 文件,Skill 只记录变量名、读取方式和轮换提醒;由脚本在运行时加载,不让 Agent 为了调用接口先把整个文件读进对话。
Skill 是规则,不是保险柜
Codex Skill 的定位是「让下一次 Agent 知道怎么做」。
它适合保存流程、规则、命令模板、路径约定、失败边界和经验教训。例如「Figma 导图优先走 REST Images API」「导出后检查尺寸和透明角」「如果接口返回 Invalid token,先判断认证问题,不要误判为节点导出失败」。
第一,Skill 是长期文本。它可能被复制、打包、同步、备份,也可能进入 Git 仓库。密钥一旦写进去,就很难确定后来经过了哪些路径。
第二,Skill 会被 Agent 读取。只要未来某次任务触发这个 Skill,密钥就可能进入上下文、日志或中间摘要。就算 Agent 没有主动打印,明文也已经出现在处理链路里。
第三,Skill 通常是跨任务复用的。一个 token 本来只服务 Figma 导图,却可能因为 Skill 被别的任务读取而扩大暴露面。
第四,密钥有生命周期。Figma Personal Access Token 当前最长只有有限有效期;API key 也应该定期轮换。把短生命周期的东西写进长期规则,会让规则不断过期,也容易让失效 token 被误当成流程问题。
更稳的分层是:
| 类型 | 适合放哪里 | 例子 |
|---|---|---|
| 长期规则 | Skill / AGENTS.md / README | 导图优先级、失败判断、检查命令 |
| 本机私有凭据 | ~/.codex/env/<skill>.env / Keychain |
FIGMA_TOKEN、APIFOX_ACCESS_TOKEN |
| 团队生产凭据 | KMS / 云平台 Secret / CI Secret | 生产 API key、部署密钥 |
| 临时运行参数 | shell env / CLI 参数 | 本次节点 ID、输出路径、是否 dry-run |
按生命周期和暴露面分开放置,规则可以迁移,凭据可以独立轮换。

官方建议保持一致
OpenAI 的 API key 安全建议很直接:不要把 key 提交到仓库,推荐用环境变量;生产环境还应考虑 Key Management Service。OpenAI 的 Quickstart 也默认让 SDK 从 OPENAI_API_KEY 这类环境变量读取密钥。
OpenAI:Best Practices for API Key Safety 明确提醒不要把 API key commit 到 repository,并建议用环境变量替代代码里的明文 key;生产环境可以考虑 KMS。
Anthropic 的建议也类似。它把 API key 泄露的常见来源指向公开仓库和第三方工具,建议云环境使用加密 Secret,本地如果用 dotenv,要把 .env 放进忽略列表;它还建议按计划轮换 key,例如 90 天一次,并尽量按用途拆分不同 key。
Anthropic:API Key Best Practices 提到不要在代码或配置文件里直接包含 key;本地 dotenv 要从版本控制排除,云环境优先使用 encrypted secret storage。
Figma 的文档则强调 Personal Access Token 是代表个人账号访问 API 的凭据。它可以用于个人脚本和本地工具,生成后只显示一次,不再需要时应撤销。Figma REST API 的认证文档也说明,个人脚本适合使用 Personal Access Token,读取文件内容需要 file_content:read scope。
Figma REST API Authentication 把 Personal Access Token 定位为个人脚本和本地工具的认证方式;Figma Help Center 说明 token 生成后只显示一次,并可以在不再使用时撤销。
Cursor 的安全文档没有规定「本地 env 应该放哪里」,但它提醒了 AI 开发工具里的关键边界:开发环境和代码数据会进入工具处理链路,安全边界需要被明确管理。即使工具提供 Privacy Mode,也不等于可以把密钥当普通文本到处放。
Cursor Security 说明了它对开发环境、代码数据、Privacy Mode 和最小权限的处理方式。对本地 Agent 场景来说,关键启发是:敏感内容要尽量减少进入 AI 请求、索引、日志和长期文本的机会。
密钥应作为运行时凭据管理,避免写进源码、长期文档或可复用指令。
为什么不是直接用 shell 环境变量
最标准的做法是 export FIGMA_TOKEN=...。
在 Codex 这类长期本机工作流里,单靠手动 export 会遇到两个问题。
第一,不同 shell session 不一定共享。今天在一个终端 export 过,明天 Codex 新开任务时可能已经没有这个变量。
第二,变量归属不清楚。如果所有工具都塞进 ~/.zshrc,后续查起来会变成一长串混杂配置:Figma、APIFox、TinyPNG、OSS、各种测试 token 全在一起。
这里采用一个折中方案:在 Codex 自己的本机目录下建立私有 env 文件夹。
~/.codex/env/
figma-tinypng-assets.env
apifox-mcp.env
tinypng-assets.env每个文件按 Skill 命名,格式仍然是普通 .env:
FIGMA_TOKEN=...
FIGMA_TOKEN_EXPIRES_AT=2026-09-02
FIGMA_TOKEN_RENEW_REMIND_AT=2026-08-26Skill 只记录配置位置和 FIGMA_TOKEN 变量名。脚本自己读取或由启动进程注入,Agent 只看脱敏后的存在性、到期状态和请求结果。不要用 cat、Get-Content 或调试日志把真实值输出到工具结果里,否则即使没写进 Skill,凭据仍然会进入上下文。
这个目录应该怎么保护
~/.codex/env 不是生产级 KMS。它只是本机私有配置目录。
它至少要满足几个条件。
第一,目录和文件权限要收紧。
mkdir -p "$HOME/.codex/env"
chmod 700 "$HOME/.codex/env"
chmod 600 "$HOME/.codex/env/figma-tinypng-assets.env"700 表示只有当前用户能进入目录;600 表示只有当前用户能读写文件。这样不能防住所有风险,但能减少同机其他用户或误配置脚本随手读取的机会。
第二,默认把真实凭据排除在 Git 同步之外。
检查的是最终链接目标,不是路径看起来是否在 home 下。如果 ~/.codex/env 链接到资产仓库,仍要排除真实值,优先只提交模板。私有仓库也会产生历史、clone 和备份,不等于凭据管理系统;确需同步时,要按组织允许的加密和访问控制方案处理。
第三,脚本只能验证「存在」「是否过期」「能不能访问接口」,不要打印真实值。
可以这样写:
if [ -f "$HOME/.codex/env/figma-tinypng-assets.env" ]; then
echo "figma env: present"
else
echo "figma env: missing"
fi不要这样写:
cat "$HOME/.codex/env/figma-tinypng-assets.env"第四,过期时间也要写进配置。
FIGMA_TOKEN_EXPIRES_AT=2026-09-02
FIGMA_TOKEN_RENEW_REMIND_AT=2026-08-26这两个值不是密钥,可以出现在 Skill 或提醒里。它们能帮助 Agent 在执行前判断 token 是否快过期,避免把过期认证误判成接口、节点或脚本问题。
一个具体例子:Figma 导图
这次需求很具体:把 Figma 节点导成 2x PNG。手动操作很简单,选中节点,右侧 Export 选 2x PNG,点击导出。
为了自动化这件事,最稳的路径是 Figma REST Images API。
curl \
-H "X-Figma-Token: $FIGMA_TOKEN" \
"https://api.figma.com/v1/images/<FILE_KEY>?ids=<NODE_ID>&format=png&scale=2"第一,Figma Personal Access Token 要用 X-Figma-Token header。至少在这次验证里,同一个 token 用 Authorization: Bearer 会返回 Invalid token。
第二,接口第一步返回的是图片 URL,不是直接返回 PNG 文件。脚本拿到 URL 后要立刻下载到本地,再做尺寸、透明角和可见内容检查。图片 URL 有时效性,不能把它当长期资源。
这段逻辑对应的 Skill 规则应该写成这样:
- Figma REST Images API 默认从 `$HOME/.codex/env/figma-tinypng-assets.env` 读取 `FIGMA_TOKEN`。
- 使用 `X-Figma-Token` header 调用 API。
- 如果返回 `Invalid token` / `Unauthorized` / `Forbidden`,先判断认证问题,不要误判成节点导出失败。
- 导出后检查 PNG 类型、物理尺寸、四角 alpha 和可见像素范围。这段 Skill 规则只记录操作方式,真实 token 由运行脚本加载。
什么时候应该升级到 Keychain 或 KMS
~/.codex/env 适合个人本机、内部临时工具和低频脚本。它的优点是直观,Codex 容易读取,按 Skill 分文件也容易维护。
如果凭据很敏感,或者它能操作真实生产环境,就应该优先放到系统级凭据管理里。macOS 上可以考虑 Keychain;团队云环境里应该使用 AWS Secrets Manager、GCP Secret Manager、Azure Key Vault、Vercel Environment Variables、GitHub Actions Secrets 等。
如果脚本要在 CI/CD 里跑,就不要依赖 ~/.codex/env。CI 应该从平台 Secret 注入环境变量,脚本仍然只读取变量名。
如果 token 需要多人共用,也不要把个人 PAT 复制给别人。Figma 文档里也区分了个人 token、组织级 plan access token 和 OAuth app。个人本地脚本可以用 PAT,团队自动化更适合组织级或 OAuth 机制。
可以按场景判断:
| 场景 | 推荐方式 |
|---|---|
| 个人本机 Skill 脚本 | ~/.codex/env/<skill>.env |
| 高敏感本机凭据 | macOS Keychain / 1Password CLI |
| CI/CD | GitHub Actions Secrets / 云平台 Secret |
| 生产服务 | KMS / Secret Manager |
| 多用户 SaaS 集成 | OAuth |
| 组织级自动化 | 组织级 access token 或平台托管凭据 |
给 Agent 的规则要写清楚
Skill 需要写明凭据来源、日志范围、失败判断、轮换提醒和备份要求,让下一次执行任务的 Agent 也能遵守这些边界。
第一,密钥来源。
默认从 `$HOME/.codex/env/<skill-name>.env` 读取,不从 Skill 正文读取真实 token。第二,日志边界。
只输出 token 是否存在、是否过期、接口认证是否成功,不输出 token 值。第三,失败归因。
认证失败时,先报告 token 失效或权限不足,不要继续尝试和认证无关的本地拼接方案。第四,轮换提醒。
如果 env 文件里有 `*_EXPIRES_AT`,到期前一周提醒用户重新生成。第五,备份边界。
备份 Codex 数据时默认排除 `$HOME/.codex/env`,只备份 env 示例模板。Agent 不会天然知道「这个文件是规则,那个文件是凭据」,需要由这些规则明确哪些内容可以读取、记录或备份。
底线很简单
个人本机 Codex 工作流需要把凭据读取和规则维护分开:Skill 记录怎么读取凭据,真实值由运行进程加载。
- Skill 里只写变量名、路径、读取方式、权限要求和失败判断。
- env 文件里可以写真实值,但必须放在本机私有目录并限制权限。
- 终端输出、文章、日志、Git diff、对话回复里都不要出现真实密钥。
- 过期时间和提醒时间可以写进 Skill,因为它们不是密钥。
- 一旦发现密钥进入仓库或对话摘要,要按泄露处理,立刻撤销并重新生成。
以后增加 Figma、APIFox、TinyPNG 等工具时,先确认凭据由哪个进程读取、会不会出现在工具输出、是否跟随链接进入 Git。文件放对目录只是第一步,调用和同步过程也要保住这个边界。