AI 编程安全清单:个人开发者最容易漏的 7 处

AI 编程工具拿到的权限,比大多数人以为的大:能读你整台机器的文件(默认策略下连凭证文件都在内),能替你执行命令,还能联网。装完就开工,相当于把家门钥匙插在锁上出门。
这篇是自查清单,不是科普。七条,每条都给你一个能直接执行的动作:可能是几行配置,可能是一个命令,也可能只是要你打开一个文件看一眼。全部过一遍大概二十分钟,新装工具当天做最划算。
1. 密钥,别躺在 AI 读得到的文件里
AGENTS.md、README、脚本注释,都是 AI 每次会话要读的东西。密钥写在这些文件里,它会跟着上下文一起进到模型的请求里去——而这些文件十有八九还进了 git 仓库,等于发了一遍又一遍。
三个动作:
- 密钥挪到环境变量,文件里只留变量名
- 确认
.env被忽略了,在项目根目录跑git check-ignore .env,没有任何输出就是没被忽略,赶紧补进.gitignore - 顺手搜一遍已有的 Markdown 文件:
grep -rniE "api[_-]?key\s*[:=]" --include="*.md" .
Windows 原生终端没有 grep,Git Bash 里跑同样的命令,或者用 PowerShell:Get-ChildItem -Recurse -Include *.md | Select-String "api_key"。
搜出来的结果自己过一眼。真挖出密钥,光从文件里删掉没用——进过 git 历史的东西删不干净,直接去平台作废重发一把。
2. 凭证文件,单独上锁
工具的默认读取策略允许读整台机器,包括 ~/.ssh 和云厂商的凭证文件。这层没人替你挡,得自己配。
Claude Code(v2.1.187 起)的做法是给凭证单独列拒绝名单,写在项目的 .claude/settings.json 里:
{
"sandbox": {
"enabled": true,
"credentials": {
"files": [
{ "path": "~/.ssh", "mode": "deny" },
{ "path": "~/.aws/*", "mode": "deny" }
],
"envVars": [
{ "name": "GITHUB_TOKEN", "mode": "deny" },
{ "name": "AWS_SECRET_ACCESS_KEY", "mode": "deny" }
]
}
}
}
两个限制要知道:没有内置的默认名单,你不写就是不管;这份配置只影响沙箱化的 Bash 命令,想让所有子进程都清掉云厂商凭证,另设 CLAUDE_CODE_SUBPROCESS_ENV_SCRUB 环境变量。
这是整套沙箱里我觉得最实用的一块。SSH 私钥这种东西,一次泄露就是长期后门。
3. 权限规则:先 deny,再 allow
新装工具别急着全放行,先把危险操作否定掉,再放开干活要用的:
{
"permissions": {
"deny": [
"Bash(rm -rf *)",
"Bash(curl *)",
"Bash(wget *)"
],
"allow": [
"Bash(git *)",
"Bash(npm test)"
]
}
}
规则评估按 deny → ask → allow 的顺序走,第一个匹配的说了算。宽泛的 Bash(rm *) 会盖住更具体的 Bash(rm *.tmp),这个设计是防漏网的,deny 里画宽一点没关系,allow 才要给得吝啬。
权限弹窗最怕的是你麻。弹多了开始无脑点同意,安全配置形同虚设。deny 列表越完整,弹窗越少,人反而守得住。
4. 高危命令,上一道它撞不开的围栏
权限规则管的是"问不问你",围栏管的是"根本过不去"。ZCode 的 Hook 机制干这个:AI 每次要执行命令,先过你写的脚本,撞上黑名单直接拦。干过 pre-commit 的一眼就懂:husky 拦你的提交,hook 拦 AI 的动作。
配置在 ~/.zcode/cli/config.json 里加一段 PreToolUse,指向一个脚本:
// hooks/guard.mjs
const PATTERNS = [
/rm\s+-\w*(?:r\w*f|f\w*r)/, // rm -rf、rm -fr 这类合并写法
/git\s+push\s+.*--force/, // 强制推送
/git\s+reset\s+--hard\s+origin/, // 本地强制对齐远端
/drop\s+(table|database)/i, // 删表删库
];
let raw = "";
process.stdin.on("data", (chunk) => (raw += chunk));
process.stdin.on("end", () => {
const input = JSON.parse(raw);
const command = input.tool_input?.command ?? "";
if (PATTERNS.some((pattern) => pattern.test(command))) {
console.log(JSON.stringify({
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: `命令命中黑名单:${command}`,
},
}));
}
});
四条黑名单是按我自己担心的场景写的,你的清单大概率跟我不同,照着你的恐惧写。
配的时候三个坑提前说:"enabled": true 不写整套 hook 是停用的,白配;项目级配置当前整体不生效,只能配在用户级;改完配置要重开会话才生效,正在跑的会话不热更新。
黑名单认的是已知写法,rm -r -f 拆成两个参数写,上面的正则就漏了。真会出事故的命令,把思路倒过来做白名单——只放行明确确认过的,其余一律拦。白名单难写,但栏杆是真密。
5. 不信任的代码,关起来跑
前面几条拦的都是 AI 自己的念头,还有一层没人拦:AI 拉起来的代码想干什么。来路不明的脚本、依赖一大串的项目,跑之前先上沙箱。
Claude Code 里输 /sandbox 就有:macOS 用系统自带的 Seatbelt,开箱即用;Linux 和 WSL2 先装 bubblewrap 和 socat 两个包;原生 Windows 不支持,得进 WSL2 里跑。
沙箱有两个默认值容易想当然:文件系统上默认只让写工作目录和临时目录,但读取放开到整台机器。所以第 2 条的凭证保护要单独配,这两件事不互相包含。网络默认全禁,第一次访问某个域名会弹出来问你,选"是"只对当前会话有效,要持久化得写进 allowedDomains。看到不认识的域名先去搜一下它是什么,别手快。
要求再高一档的,敏感项目直接上 Dev Container,整个开发环境关在容器里,这是目前最强的隔离级别。
6. 插件和 MCP server,装之前过一眼
新装一个 MCP server 会弹信任确认,多数人想都没想就点了。第三方插件带的 hook 和内置的一样照跑——装市场插件前,把它的 hooks.json 和脚本文件打开看一眼,它要执行的每个脚本都会在你的机器上跑。
这不是理论风险。我自己踩过一次:一个第三方集成往全局配置里写了两处空 matcher,结果同一份文件校验不过,它自己的 hook 和我配的 MCP 服务一起下线,界面上没有任何提示,翻日志才找到病因。三方的代码写进你的全局配置,出事是连坐的。
装之前看三样:要执行的脚本本体、申请的权限范围、配置写在哪个作用域。看不懂的插件不装,市场里的东西不比 npm 干净。
7. 来历不明的模型,别喂敏感仓库
8 月 20 号 OpenRouter 上冒出来一个 Ox Alpha,没有厂名,来历一栏写着 stealth——这种匿名挂出的模型这两年不少见,GLM-5 发布前也匿名挂过一阵。它规格很漂亮:100 万 token 上下文,宣称零数据留存,免费开放了一周(窗口现在关了)。
指纹测试好玩归好玩,我想说的是另一件事:数据条款是模型方自己写的声明,"零留存"和"你能验证零留存"是两回事。社区用报错码、tokenizer 指纹把它猜到智谱头上,也只是猜。
拿免费大窗口跑开源项目、玩具项目,怎么玩都行。公司代码、带用户隐私的项目,喂给认得出出处的模型。判断就两条:留不留存、会不会拿去训练。答不上来的,别把敏感东西放进去。
写在最后
七条过完,这挡不住所有攻击,但最常见的几扇门都锁上了。工具版本在变,配置项跟着变,这份清单我会定期重过,哪条失效了在评论区更新。
AI 编程这条线我会一直写,新工具上手和踩坑实录都会记,关注了新文直接推到订阅里。

浙公网安备 33010602011771号