术语表

「.env」是什么 — 环境变量文件泄露会发生什么

.env 是把数据库认证、API key、加密密钥等机密值与应用分开保存的配置文件,一旦放进公开目录,所有机密都可能被读取。讲解正确存放位置、git 防护、轮换与自查方法。

发布于 2026-06-07 更新于 2026-10-06 3 分钟阅读
本页目录

.env 非常方便,几乎所有现代框架都会用它。但只要存放位置弄错一处,里面的所有机密就可能被任何人读取。本文从零开始讲解它的含义和防护方法。

再讲细一点

应用里有「随环境而变的值」和「不想给人看到的值」。比如数据库密码、外部服务的 API key、用来加密会话的密钥等。如果把这些直接写死在源代码里,一旦共享代码,秘密也会跟着一起泄露。

于是,把这些集中到 .env 这一个文件里,代码则以「环境变量」的形式读取它们。Next.js、Laravel、Rails 等许多框架都采用这种方式。

内容是纯文本,一行一个「名称=值」(以下的值都是占位符)。

APP_ENV=production
DB_HOST=127.0.0.1
DB_PASSWORD=your-db-password-here
PAYMENT_API_KEY=your-payment-api-key-here

把配置放在代码之外的做法,因 Web 应用设计指南「The Twelve-Factor App」而普及。它判断配置是否被正确分离的标准是:代码库能否随时开源,而不泄露任何认证信息。.env 是在开发阶段实现这一思路的便利容器。

与相似概念的区别

下面是最常与 .env 混淆的几样东西。其中只有一部分适合存放机密。

名称是什么能放机密吗?
环境变量操作系统或容器传给运行中进程的值可以(生产环境的常规做法)
.env把环境变量汇总到一个文件中可以,但绝不能放进公开目录或 Git
.env.example只列出名称、值留空的样例不可以(本来就是要提交的)
NEXT_PUBLIC_* / VITE_*被嵌入浏览器端 JavaScript 的变量不可以(任何人都能读取)
密钥管理服务存放机密值的云服务可以;通过权限和审计日志管理

第四行最容易被忽视。Next.js 会把以 NEXT_PUBLIC_ 开头的变量、Vite 会把以 VITE_ 开头的变量的值,在构建时嵌入发送给浏览器的 JavaScript。即使写在 .env 里,带这些前缀的变量也会变成公开的。

为什么是「最危险的文件」

.env 在一个文件里汇集了多把钥匙,所以这里一旦泄露,损害就会一下子扩散开来。把每把钥匙「泄露后会发生什么」并列出来,就能看出有多严重。

泄露的值会发生什么
数据库认证信息数据被读取、篡改、全部删除
外部 API key被冒名使用、违规扣费
加密密钥(如 Laravel APP_KEY、签名密钥)会话伪造、冒名登录
OAuth 机密关联应用被接管

事实上,.env 被公开是事故的经典戏码。→ .env 曾向全世界公开的故事

真实案例:被公开的 .env 成为攻击目标

  • 大规模勒索活动(2024 年):据一家安全公司的研究团队报告,有一项活动以 11 万个域名为目标,收集暴露在 Web 服务器上的 .env 文件,利用其中的云认证信息窃取数据并索要赎金。被收集的变量超过 9 万个,其中约 7,000 个属于云服务,约 1,500 个属于社交媒体账号。原因并非云服务商的漏洞,而是公开了 .env 的组织自身的配置错误
  • Vercel(2026 年 4 月):内部系统遭未授权访问,导致部分客户的环境变量被读取——被读取的是存放在「值可以再次显示」类别中的变量 → 详细文章
  • 公开仓库(2026 年的一项研究):发布在 GitHub 上的认证信息中,有超过 54 万个在研究时仍然有效。只要认证信息没有被吊销,删除文件或历史都无济于事 → 详细文章

第一个案例说明,被公开的 .env 不是被人偶然浏览发现的,而是被自动化地大规模收集。不要以为小网站就不会被发现。

泄露的典型模式=存放位置的失误

最大的原因是「把应用本体整个放进公开目录(docroot)」。本该只暴露 public/,结果却公开了它的上级目录,连 .env 都能被取到。

✗ 危险(本体直接放在公开根目录下)

public_html/
├─ .env   ← 能被读到!
├─ app/
└─ public/

✓ 安全(本体在外,只公开 public)

app-root/
├─ .env   ← 无法到达
├─ app/
└─ public_html/ → public/
本体放在 docroot 之外,公开的只有 public/。仅此一点,.env 就变得无法到达。

除了存放位置,它还会通过以下途径泄露:

  • 提交到 Git(公开仓库会立刻公开;私有仓库中所有有访问权限的人都能看到)
  • 把 .env.bak、.env.old 等备份留在公开目录中
  • 发布容器镜像或分发用 zip 时,.env 仍包含在内
  • 如上所述,把机密放进 NEXT_PUBLIC_ / VITE_ 变量

防护方法

1

不要放进公开目录

应用本体放在 docroot 之外,公开的只有 public/ 等。在虚拟主机上的具体步骤见 这篇文章。

2

不要提交到 git

在 .gitignore 里加入 .env*,只共享把值留空的 .env.example。

3

泄露后全部轮换

不只是能确认到的那一个,而要把 .env 里的钥匙全部更换。按照已被看到的前提来行动。

4

定期自查

养成确认自己网站上 /.env 是否能被打开的习惯。

如何检查自己的网站和仓库

自查(仅限你自己拥有的域名)

# 返回 200 且有正文就说明已公开。403/404 则暂时没问题
curl -sI https://你的域名/.env | head -1
curl -sI https://你的域名/.git/config | head -1

养成每次发布都做一次这项确认的习惯,就能及早发现存放位置的失误。

网站外部和仓库内部都要检查。

  1. 对于已验证所有权的网站,网站安全诊断会一次性检查 /.env、/.env.local、/.env.bak 等路径
  2. 在仓库中运行 git log --all --oneline -- .env,查看它是否曾被提交过。如果有输出,请吊销其中包含的钥匙
  3. 把配置或代码贴进机密泄露扫描器,找出写死的 API key 或私钥(在浏览器中运行)
  4. 检查 NEXT_PUBLIC_ / VITE_ 变量的列表,确保没有机密被打包进构建后的 JavaScript

本站观点:.env 的存放位置和钥匙的吊销方法要一起决定

大多数 .env 事故,都始于一个放错位置的文件。而让损害在之后扩大的,是没有事先定好更换钥匙的流程。

本站建议:如果使用 .env,不仅要把它放在公开目录之外、不进入 Git,还要事先写下其中每把钥匙的吊销和重新签发方法。在生产环境中,改用云端的密钥管理服务,或改用「值无法再次显示」的环境变量,可以进一步减少泄露途径。

出处(一手资料)

  • The Twelve-Factor App, "III. Config" — 12factor.net(把配置存放在环境变量中;能否开源的判断标准)
  • Next.js docs, "Environment Variables" — nextjs.org(NEXT_PUBLIC_ 会在构建时被内联进 JavaScript;不要提交 .env 文件)
  • Vite docs, "Env Variables and Modes" — vite.dev(VITE_ 变量会暴露给客户端代码)
  • Unit 42 (Palo Alto Networks), "Leaked Environment Variables Allow Large-Scale Extortion Operation in Cloud Environments" (August 15, 2024) — unit42.paloaltonetworks.com

接下来读

分类编号

CWE 对导致漏洞的弱点类型进行分类,MITRE ATT&CK 对攻击者的技术进行分类。两者均由 MITRE 维护,广泛用于标注漏洞信息和检测规则。

CWE™: Copyright © 2006–2026, The MITRE Corporation. CWE is a trademark of The MITRE Corporation. The MITRE Corporation hereby grants you a non-exclusive, royalty-free license to use CWE for research, development, and commercial purposes. Any copy you make for such purposes is authorized on the condition that you reproduce MITRE’s copyright designation and this license in any such copy. CWE Terms of Use

FAQ

Q.env 可以提交到 git 吗?
A

不可以。务必把 .env 加入 .gitignore。作为替代,只提交把值留空的 .env.example,用来共享「需要哪些 key」。

Q.env 哪怕只泄露了一个,要更换什么?
A

不仅是能确认到的那一个,而要把 .env 里的钥匙全部轮换。优先顺序是「外部 API、OAuth 机密 → 加密密钥 → 邮件 → 数据库」。按照已被看到的前提来行动才安全。

Q怎么确认 .env 是否泄露了?
A

用浏览器打开自己网站的 https://你的域名/.env,如果内容被显示出来,就说明已经公开了(返回 200 且能看到正文就出事了)。如果没显示而是 403/404,那暂时没问题。

Q.env 是什么意思?
A

通常读作「dot env」。env 是 environment(环境)的缩写,开头的点在 Linux 和 macOS 上表示隐藏文件。文件内容是 DB_PASSWORD=… 这样一行一个的「名称=值」,应用会把它们作为环境变量读取。

Q可以把机密放进以 NEXT_PUBLIC_ 或 VITE_ 开头的变量吗?
A

不可以。在 Next.js(NEXT_PUBLIC_)和 Vite(VITE_)中,带这些前缀的变量的值会在构建时被嵌入发送给浏览器的 JavaScript,任何人都能读取。写在 .env 里并不意味着它是秘密。API key 只在服务器端代码中使用,不要加这些前缀。

Q不小心把 .env 推送到了 GitHub,该怎么办?
A

首先吊销并重新签发其中包含的所有钥匙。删除文件或改写历史,都无法消除可能已经存在的副本,所以吊销要先于删除。之后把 .env 加入 .gitignore,并从历史中移除。