AI 编程 IDE 正从“补全几行代码”走向“自主完成长程任务”。能力边界扩大后,工具读取的数据也可能从当前文件扩展到整个项目、依赖配置,甚至完整的 .git 历史。近期引发讨论的 ZCode 事件中,其端到端长程任务功能会打包上传项目的完整 Git 历史,相关行为已在官方社群得到确认,并影响了 GLM-5.5 的发布安排。
这件事真正值得关注的,不只是某一款产品是否上传了数据,而是开发者经常默认“本地仓库等于当前工作区”。实际上,.git 目录可能比源码目录包含更多敏感信息。
.git 为什么比当前代码更敏感
删除一个文件,并不意味着它已经从 Git 仓库消失。只要相关提交仍然可达,历史对象中就可能保留:
- 曾经提交过的
.env、云服务密钥和数据库密码; - 已删除的内部接口、调试代码和安全修复细节;
- 未合并分支、标签以及历史版本中的商业逻辑;
- 提交者姓名、邮箱、提交时间和提交说明;
- Git remote 地址、子模块地址及内部代码托管结构;
- 大型二进制文件、数据样本或客户配置。
因此,.gitignore 只能阻止未跟踪文件在未来被加入版本库,不能清除已经进入历史的数据。即使当前目录看起来很干净,完整 Git 历史仍可能包含多年前误提交的凭据。
对于能够调用终端、搜索仓库和自动修改文件的 AI Agent,还要额外考虑三个边界:
- 读取边界:工具能读取当前文件、整个工作区,还是工作区之外的主目录?
- 上传边界:哪些内容会离开本机,是代码片段、索引、终端输出,还是完整压缩包?
- 执行边界:工具能否运行 Shell、读取环境变量、访问 SSH Agent 或连接内网?
只讨论“模型是否用代码训练”并不够。即使服务承诺不训练,数据在传输、缓存、日志、故障排查和第三方处理环节仍然存在暴露面。
先检查仓库历史里到底有什么
在把现有仓库交给任何 AI 工具之前,可以先做一次历史审计。下面的命令只读取本地 Git 数据,不会上传内容。
查看历史中是否出现过常见敏感文件:
git log --all --full-history --name-only --pretty=format: \
| sort -u \
| grep -Ei '(^|/)(\.env|id_rsa|credentials|secrets?\.(ya?ml|json)|.*\.(pem|p12|key))$' \
|| true
找出历史中超过 5 MiB 的 Git Blob,避免在不知情的情况下上传数据库、模型或压缩包:
git rev-list --objects --all \
| git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' \
| awk '$1 == "blob" && $3 >= 5 * 1024 * 1024 {printf "%.2f MiB\t%s\n", $3/1024/1024, $4}' \
| sort -nr
如果团队已经安装 Gitleaks,还可以扫描整个 Git 历史,而不是只扫描当前工作区:
gitleaks git . --redact --report-format json --report-path gitleaks-report.json
--redact 可以减少扫描报告再次泄露凭据的风险。需要注意,任何密钥一旦进入过版本历史,都应该视为已经暴露:正确处理方式是立即吊销或轮换密钥,然后再使用 git filter-repo 等工具清理历史。仅仅删除文件并重新提交并不够。
给 AI Agent 创建不带历史的最小工作区
如果任务只是修改当前版本的代码,通常没有必要把 .git、本地环境变量、证书和构建产物一起交给工具。可以创建一个临时副本,只复制完成任务需要的文件。
将下面脚本保存为 make-ai-workspace.sh,赋予执行权限后,把仓库路径作为第一个参数传入:
#!/usr/bin/env bash
set -euo pipefail
src="${1:-.}"
dst="$(mktemp -d "${TMPDIR:-/tmp}/ai-workspace.XXXXXX")"
rsync -a \
--exclude='.git/' \
--exclude='.env' \
--exclude='.env.*' \
--exclude='*.pem' \
--exclude='*.key' \
--exclude='*.p12' \
--exclude='node_modules/' \
--exclude='.venv/' \
--exclude='dist/' \
--exclude='build/' \
"$src/" "$dst/"
if find "$dst" -name .git -o -name '*.pem' -o -name '*.key' | grep -q .; then
echo '拒绝继续:临时工作区仍包含敏感文件。' >&2
exit 1
fi
printf 'AI 临时工作区:%s\n' "$dst"
printf '检查完成后再让工具打开该目录。\n'
运行方式:
chmod +x make-ai-workspace.sh
./make-ai-workspace.sh /path/to/your/repository
这不是完整的数据防泄漏方案,但它能有效缩小默认暴露范围。使用前应根据项目增加排除项,例如客户数据、移动端签名文件、Terraform state、Kubernetes Secret 和内部文档。
任务完成后,不要直接用临时目录替换原仓库。更稳妥的流程是审查差异,再人工应用修改:
diff -ruN \
--exclude='.git' \
--exclude='node_modules' \
/path/to/your/repository/ /tmp/ai-workspace.xxxxxx/
如果 AI 工具必须依赖 Git 来生成 diff,可以在临时目录中重新初始化一个无历史仓库:
cd /tmp/ai-workspace.xxxxxx
git init
git add .
git -c user.name='AI Workspace' \
-c user.email='ai-workspace@localhost' \
commit -m 'Sanitized baseline'
这样工具仍可使用 git diff 和回滚能力,但看不到原仓库的提交历史、分支、remote 和作者信息。
团队引入 AI 编程工具时应问什么
个人开发者可以通过临时副本降低风险,企业团队则需要把它变成可验证的准入流程。采购或启用工具前,至少确认以下问题:
- 产品是否明确列出会读取和上传的文件、元数据及 Git 对象?
- 长程任务、代码索引、崩溃报告和普通补全是否采用不同的数据路径?
- 上传前是否展示文件清单、数据体积和目标域名,并允许用户取消?
- 是否支持排除
.git、指定目录和文件类型?排除规则是在本地生效还是服务端生效? - 数据传输和静态存储是否加密,保留期多长,谁可以访问?
- 用户能否删除服务端副本,删除是否覆盖缓存、日志和备份?
- 数据是否用于训练、人工审核或转交第三方模型服务?
- Agent 的 Shell 权限、网络权限和工作区外访问能否分别关闭?
- 企业版是否提供审计日志、域名白名单和集中策略?
还应对不同仓库分级。开源示例项目可以允许更宽松的配置;包含客户数据、未公开产品、生产配置或受监管信息的仓库,应默认禁止使用外部 AI Agent,除非完成安全评估并采用企业隔离方案。
更可靠的采用方式:默认不信任,按任务授权
AI 编程工具不应自动获得“整个开发机”的权限。更稳妥的默认策略是:只开放一个经过清理的工作区,只提供完成当前任务所需的文件,Shell 命令需要确认,敏感环境变量不注入,网络访问按域名限制。
落地时可以采用这份简短检查表:
- 扫描当前文件和完整 Git 历史中的密钥;
- 对已经提交的凭据执行轮换,而不只是删除;
- 默认排除
.git、.env、证书、构建产物和客户数据; - 用临时副本或容器承载 AI 任务;
- 开启上传提示、命令确认和审计日志;
- 定期检查工具升级后权限与隐私设置是否发生变化;
- 对核心私有仓库保留禁用外部 Agent 的选项。
效率和安全并非只能二选一。真正的问题是:工具获得了哪些数据、为什么需要这些数据,以及开发者能否在上传前做出清晰、可撤销的授权。任何无法回答这三个问题的 AI 编程工具,都不应直接接触高价值代码仓库。