Loading

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

AI 编程安全清单

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 先装 bubblewrapsocat 两个包;原生 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 编程这条线我会一直写,新工具上手和踩坑实录都会记,关注了新文直接推到订阅里。

posted @ 2026-09-08 23:19  拓荒者IT  阅读(24)  评论(0)    收藏  举报