全部指南
严重程度:严重配置错误

暴露的 .git 目录:藏在眼皮底下的源代码泄露

当 Web 服务器在提供应用文件的同时也提供 .git 目录时,攻击者可以下载足够多的对象来重建你的完整源代码——包括曾经提交过的每一个密钥,即使它在后来的提交中已被删除。AppSafe 将此标记为严重问题。

这是什么

Git 将完整的仓库——每个文件、每次提交、每个分支的最新提交——存储在项目根目录下隐藏的 .git 目录中。如果该目录最终位于 Web 根目录内,而服务器又没有阻止对它的访问,那么 /.git/config、/.git/HEAD 以及 /.git/objects/ 下的对象存储都可以被公开下载。

从泄露的 .git 目录重建完整源代码非常简单。git-dumper 等工具会先获取索引,再拉取所有被引用的对象,最终得到一个完全可用的工作副本。攻击者不需要 shell 访问权限——只需要一个浏览器。

为什么重要

你的源代码几乎肯定包含会增加风险的信息:硬编码的 API key(通常在较早的提交中)、数据库结构、内部端点路径、业务逻辑和认证流程。即使当前没有提交任何密钥,历史记录中也充满了攻击者可以利用的材料。

Git 历史在设计上就是永久的。多年前提交、随后被删除的密钥仍然存在于对象存储中,并会与其他所有内容一起被下载。轮换密钥是消除其威胁的唯一方法。

如何修复

在 nginx 中阻止 .git

拒绝所有路径以 /.git/ 开头的请求。返回 404 而不是 403,以免确认该目录存在。

location ~ /\.git {
  deny all;
  return 404;
}
将 .git 放在 Web 根目录之外

最可靠的修复方法是从一开始就不要把 .git 目录部署到文档根目录中。调整构建流程,让编译产物输出到单独的 public/ 目录,并且只部署该目录,而不是项目根目录。

验证已被阻止

部署修复后,在浏览器中请求 https://yourdomain.com/.git/config。它应该返回 404,而不是你的 Git 配置内容。AppSafe 会在每次扫描时重新检查这一点。

轮换所有曾经提交过的密钥

如果该目录曾经可访问,请将任何提交中出现过的每一个 API key、密码和令牌都视为已泄露,并进行轮换——仅删除提交是不够的,因为该对象仍然存在于攻击者可能已经下载的 pack 文件中。

常见问题

我部署在托管平台上(Vercel、Netlify、Fly.io)——我有风险吗?

从源代码构建的托管平台通常只部署构建产物,因此不会提供 .git 目录。风险更高的是 VPS 部署、从项目根目录构建的 Docker 容器,或者复制整个工作树的静态站点导出。

AppSafe 实际检查的是什么?

AppSafe 会请求 /.git/config 和 /.git/HEAD,并检查响应正文是否像真正的 Git 文件(匹配 [core] 或 ref: 模式)。不是 Git 内容的通用 200 页面不会被标记。

我可以直接删除服务器上的 .git 目录吗?

可以,如果你只需要部署的文件来运行应用。但要确保你的部署流程不会在下次推送时把它复制回来。在 Web 服务器层面阻止访问是一种双重保险,可以应对部署脚本不一致的情况。

你的应用受影响了吗?

AppSafe 一次免费扫描,就能检查这个问题以及数十项其他问题。

免费扫描我的应用