
摘要:AI 安全不是让程序不用密码,而是让密码只在本地受控环境里被程序读取,不在对话框里被 AI 看见。正确做法是:AI 只看变量名、配置结构、调用方式和脱敏日志;真实凭证放进操作系统环境变量、密码管理器、本地
.env或云厂商本地 profile;代码执行时从本地读取,聊天记录里只留下占位符。
0. 结论先行
真实凭证永不进入 AI 对话。
但这不等于程序不能使用凭证。
正确架构是四层:
AI 对话层:只放问题、结构、假值、变量名、脱敏日志本地执行层:读取环境变量、密码管理器、本地 .env、云厂商 profile权限控制层:限制命令、确认高风险动作、禁止打印密钥泄漏处置层:一旦真实凭证进入对话,直接轮换和吊销一句话:
凭证可以被本地程序读取,不能被对话框读取。
很多人把“不要把密码给 AI”理解成“AI 没法帮我排错”。这不对。
AI 不需要知道真实密码。
AI 只需要知道程序如何读取密码。
你可以告诉 AI:
DATABASE_URL=<your_database_url>OPENAI_API_KEY=<your_api_key>REDIS_URL=<your_redis_url>你不应该告诉 AI:
DATABASE_URL=postgres://real_user:real_password@real_host:5432/prodOPENAI_API_KEY=sk-real-secret-valueREDIS_URL=redis://:real_password@real_host:6379前者是结构。
后者是钥匙。
AI 需要的是接口,不是钥匙。
1. 为什么“不给真实值”不影响 AI 干活
排错时,AI 真正需要的通常不是真实凭证,而是这几类信息:
变量名是什么 程序在哪里读取变量 SDK 怎么初始化 报错发生在哪一步 返回的是 401、403、timeout,还是 DNS 解析失败 本地环境是否真的设置了变量 调用链有没有把凭证传到正确位置
这些信息都可以不暴露真实值。
例如你问 AI:
我的 Node.js 项目通过 process.env.OPENAI_API_KEY 读取 API Key。启动时报 401。我已经确认环境变量存在,但不确定 SDK 初始化方式是否正确。下面是脱敏后的代码和错误信息。这就够了。
AI 可以检查初始化顺序、变量名拼写、加载 .env 的时机、SDK 版本、请求头格式、错误处理逻辑。
它不需要看到 sk-... 后面那串真实字符。
说白了,你要让 AI 看门锁结构,不是把钥匙递过去。
这件事最容易在赶进度时被忘掉。
因为 AI 会用很自然的语气说:
“请提供完整配置文件。”
“请粘贴完整报错日志。”
“为了定位问题,我需要看到环境变量。”
这些话听起来专业,但你要在脑子里自动翻译一遍:
可以给结构。不能给真实值。2. 安全给法一:给结构,不给真实值
个人使用 AI 时,最简单的安全动作,是把所有“真实值”替换成“占位值”。
可以给 AI:
不应该给 AI:
.env | |
printenvcat .env、完整请求头 |
如果你不确定某段内容是不是敏感,默认按敏感处理。
安全上有一个很朴素的判断:
这段内容如果发给一个陌生外包,你会不会犹豫?
如果会,那就不要直接发给 AI。
AI 对话框不是保险柜。
3. 安全给法二:把真实凭证放进本地环境变量
最常见、也最容易落地的做法,是把真实凭证放进本地环境变量。
AI 写代码时只写:
const apiKey = process.env.OPENAI_API_KEY;或者:
import osapi_key = os.environ["OPENAI_API_KEY"]AI 知道变量叫 OPENAI_API_KEY。
但它不知道真实值是什么。
代码执行时,本地进程从你的 shell、操作系统环境或运行时环境里读取真实值。只要工具没有把环境变量内容打印回对话,真实凭证就不会进入聊天记录。
这就是安全协作的核心:
AI 生成读取方式。本地环境提供真实值。这里有一个边界必须说清楚。
环境变量不是魔法保险箱。它只是比“贴进对话框”好得多,因为真实值留在本地进程环境里。
如果你让 AI 执行下面这些命令,还是会泄漏:
echo $OPENAI_API_KEYprintenvenvcat .env更安全的检查方式,是只确认“有没有”,不展示“是什么”:
test -n "$OPENAI_API_KEY" && echo "OPENAI_API_KEY is set"或者检查长度:
python -c "import os; print(len(os.getenv('OPENAI_API_KEY', '')))"关键动作不是“让 AI 不执行命令”。
关键动作是:
检查状态,不打印秘密。
4. 安全给法三:用系统密码管理器或密钥链
如果凭证价值更高,不要只放在散落的 shell 配置里。
可以放进系统级密码管理器或密钥链:
macOS Keychain Windows Credential Manager 1Password CLI Bitwarden CLI pass云厂商本地 profile
它们的意义不是让你少记密码。
而是让密码少出现。
例如用 1Password CLI 时,程序或脚本可以通过本地授权读取:
op read "op://dev/openai/api_key"你给 AI 的不是真实值,而是读取方式:
项目通过 1Password CLI 读取 OPENAI_API_KEY。读取路径是 op://dev/openai/api_key。请帮我检查脚本的错误处理和环境变量注入方式。不要输出密钥值。这比把密钥贴进对话好得多。
因为真实值不在聊天记录里,不在代码里,也不应该进入 Git。
密码管理器的另一个好处是轮换。
一旦怀疑泄漏,你可以集中换掉,而不是在十几个脚本、截图、聊天记录里追着找。
5. 安全给法四:本地 .env 可以存在,但不要上传
现实一点说,个人项目大量使用 .env。
这没问题。
问题不是 .env 存在。
问题是你把 .env 当成普通上下文发给 AI,或者提交到 Git。
个人项目至少要做到四件事:
.env 加入 .gitignore仓库提交 .env.example给 AI 看 .env.example不给 AI 看 .env可以给 AI:
# .env.exampleDATABASE_URL=postgres://user:password@localhost:5432/dbREDIS_URL=redis://localhost:6379API_KEY=your_api_key_here不可以给 AI:
# .envDATABASE_URL=postgres://real_user:real_password@real_host:5432/prodAPI_KEY=real_secret_value.env.example 是说明书。
.env 是钥匙串。
说明书可以给,钥匙串不能给。
如果 AI 要帮你排查 dotenv 加载问题,可以这样问:
这是我的 .env.example。真实 .env 留在本地,不会粘贴。程序启动时使用 dotenv 加载环境变量。请帮我检查加载顺序、变量命名和错误处理。这就够了。
6. 安全给法五:让 AI 写检查命令,但不让它打印密钥
AI Agent 可以在本地执行命令,这是效率来源,也是风险来源。
正确方式不是完全禁用执行,而是把命令分成三类。
第一类,可以直接执行:
pwdgit statusnode --versionpython --version第二类,可以执行,但必须禁止输出敏感值:
test -n "$DATABASE_URL" && echo "DATABASE_URL is set"python -c "import os; print('set' if os.getenv('API_KEY') else 'missing')"第三类,默认不要执行:
cat .envprintenvecho $DATABASE_URLcurl -H "Authorization: Bearer $TOKEN" ...注意最后一类。
有些命令本身不一定恶意,但会把凭证带进终端输出、日志、请求历史或对话上下文。
你要让 AI 学会帮你检查环境,而不是展示环境。
个人使用 AI Agent 时,可以直接在规则文件里写:
不要读取或打印 .env。不要执行 printenv、env、echo $TOKEN、echo $API_KEY。检查密钥时只能输出 set/missing 或长度。涉及删除、上传、生产环境、权限变更时必须先解释命令并等待确认。这类规则不复杂。
但它会把“临场小心”变成“默认护栏”。
7. auto mode 是护栏,不是保险箱
2026年3月,一些 AI 编码工具已经开始把权限判断放进执行层。
例如 Claude Code 的 auto mode,公开报道里描述为:工具会尝试区分低风险动作和高风险动作;普通编辑可以自动继续,涉及删除文件、暴露敏感数据、执行可疑代码等操作时,系统会阻止、重试或要求用户介入。
这个方向是对的。
因为安全不能只靠用户每次瞪大眼睛看命令。
安全必须进入权限层、执行层和审计层。
但要注意:
auto mode 是护栏,不是保险箱。
护栏能降低风险,不能替你承担全部风险。
原因很简单。
第一,分类器可能误判。安全动作可能被拦,危险动作也可能被放过。
第二,工具通常更容易识别显眼的危险命令,比如删除文件、外发数据、执行混淆脚本。但如果风险藏在普通代码改动里,边界就没那么清楚。
第三,你如果主动让工具读取 .env 并把内容打印出来,很多护栏也很难替你兜底。
所以个人使用 auto mode 时,正确心态不是:
“开了 auto,就安全了。”
而是:
“开了 auto,低级风险少一些;真正的边界仍然要靠我的本地凭证架构和规则文件。”
8. 泄漏后,不要安慰自己“应该没事”
如果真实凭证已经进入 AI 对话,按泄漏处理。
不要纠结模型到底有没有记住。
不要纠结中转站会不会保存。
不要纠结日志多久清理。
你无法证明它没有被记录。
所以直接做四件事:
轮换密钥吊销 Token检查访问日志补上规则和模板如果是生产数据库连接串,还要检查异常连接。
如果是云厂商 AccessKey,还要检查资源创建、账单、权限变更和对象存储访问记录。
如果是 Cookie 或 Session,还要退出所有设备,重置二次验证或 Passkey。
这不是夸张。
这是把“应该没事”换成“我已经处理”。
安全里最贵的不是轮换密钥。
最贵的是抱着侥幸继续跑。
9. 个人最小安全工作流
最后,把这篇文章压缩成一套个人工作流。
每次问 AI 之前,先过 7 个动作:
1. 把真实值替换成占位值2. 只给 .env.example,不给 .env3. 日志先删 Cookie、Token、手机号、连接串4. 让 AI 写读取方式,不让 AI 看真实值5. 真实凭证放本地环境变量或密码管理器6. 检查命令只输出 set/missing,不输出内容7. 一旦泄漏,直接轮换和吊销这套流程看起来麻烦。
但真正跑熟以后,它不会拖慢你。
它会让你更敢用 AI。
因为你知道边界在哪里。
第一篇里,我们说“不要回答”。
这篇的补充是:
不是所有问题都不回答。
而是:
结构可以回答,真实值不回答。
调用方式可以回答,钥匙不回答。
本地程序可以读取,聊天记录不能读取。
正如《论语·卫灵公》所言:“工欲善其事,必先利其器。”
AI 是器。
环境变量、密码管理器、权限规则,也是器。
真正安全的用法,不是把所有器都交给 AI。
而是让每个器待在自己的位置上。
我是 哇塞君。
我相信所有复杂的管理问题,背后都有一个更优的解。如果你也在自己的"铁匠铺"里面对着"天外陨铁"发愁,或许我们可以聊聊彼此锻造"匕首"的故事。
参考资料 (References & Further Reading)
- [1]
哇塞君. 不要回答!不要回答!当 AI 开始向你索要密码. (本系列安全现象篇) - [2]
OWASP Cheat Sheet Series. Secrets Management Cheat Sheet. (凭证管理、轮换、审计与最小权限) - [3]
The Twelve-Factor App. III. Config. (配置与代码分离,用环境变量承载配置) - [4]
1Password Developer. 1Password CLI. (通过本地密码管理器读取 secrets) - [5]
Bitwarden. Bitwarden CLI. (个人和团队使用命令行管理 secrets) - [6]
The Verge. Anthropic's Claude Code gets 'safer' auto mode. 2026-03-25. (Claude Code auto mode 的公开报道) - [7]
TechRadar. Anthropic gives Claude Code new 'auto mode' which lets it choose its own permissions. 2026-03-25. (auto mode 权限分类器与实验性风险说明)
夜雨聆风