第三讲:明文 Secrets 的危害——从 Git 历史到环境变量
讲完 Secrets 的定义和分类,今天咱们聊点「疼」的。
明文 Secrets 到底能造成多大的破坏?我见过太多团队,直到被拖库、被删库、被勒索,才回头去翻自己的 Git 提交历史。
你会发现,那些「藏得很深」的密码,其实一直都躺在明处。
Git 提交历史泄露——最容易被忽视的「案发现场」
我们先看一个真实场景。
你写代码写到半夜,本地数据库连不上。你直接改了 config.py,把密码写进去,git add . && git commit -m "fix db"。
第二天你意识到不对,删掉了密码行,又提交了一次。
——你觉得秘密保住了?
实际上,它永远留在了 Git 历史里。任何人把仓库 clone 下来,执行 git log -p 就能看到你的数据库密码。包括所有历史分支、标签。
git filter-branch 或 BFG Repo-Cleaner 这种强制重写历史的方式才能真正清理,但那又是一场噩梦——所有协作者都需要重新 clone。
我之前帮一个团队做安全审计,发现他们某个微服务的 .git 目录下,躺着一个裸的数据库密码。他们说「那个密码早换了啊」。我说:「你换了不等于历史里没有。任何拿到你仓库权限的人,都能跑回去看两年前你每一个 commit 的完整 diff。」
git log -p 命令。
git 历史泄露的常见形式
| 泄露方式 | 典型场景 | 危害等级 |
|---|---|---|
| .git 目录暴露 | 运维把 .git 一起部署到生产服务器 |
🔴 极高 |
| 历史提交明文密码 | 调试阶段直接写死在代码里并提交 | 🔴 极高 |
| 配置文件被跟踪 | .env / config.yaml 被 add 到 Git 后补加 .gitignore |
🟠 高 |
| 分支/标签未清理 | 功能分支包含 secrets,合并后未删除远程分支 | 🟠 高 |
| commit message 泄露 | 在描述里写了密码或 | 🟡 中 |
环境变量泄露——你以为的保护,其实到处是漏洞
很多人觉得「只要我不把密码写进代码,放到环境变量里就安全了」。
这个想法本身没错,但落地时漏洞百出。
我见过最离谱的一次:某团队把数据库连接串直接写在 ~/.bashrc 里,然后整个 /home 目录权限设置成 755 —— 任何能登录到这台机器的普通用户,都能 cat ~/some_user/.bashrc 拿到所有环境的数据库密码。
环境变量泄露的几种典型途径
- 进程列表暴露:
ps aux或/proc/<pid>/environ可以被其他进程读取。特别是在共享主机或容器中,这是重灾区。 - 日志/错误输出:应用启动时打印环境变量到 stdout;异常崩溃时 dump 全部环境变量到日志文件。
- 子进程继承:父进程设置了环境变量,它 fork 出的子进程全部能访问。如果你不小心
exec了一个脚本,密码就传过去了。 - 调试终端记录:
export SECRET=xxx打在终端里,会被记录到~/.bash_history或~/.zsh_history中。 - CI/CD 日志:Jenkins / GitLab CI / GitHub Actions 的构建日志中经常出现环境变量原文打印。
# 真实案例:某 SaaS 公司的 CI 日志里打印了 AWS_SECRET_ACCESS_KEY
# 他们用了 echo 来调试环境变量,没关掉 debug 模式
$ echo "Deploying with key: $AWS_SECRET_ACCESS_KEY"
Deploying with key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
日志与配置文件——泄露的重灾区
除了 Git 和环境变量,还有两个「裸奔」重灾区:日志文件和配置文件。
日志中的 secrets
- 请求参数里带着密码或 ,被完整的 access log 记录
- 应用 debug 日志里打印了 SQL 连接字符串
- 错误堆栈中包含环境变量或配置信息
- 审计日志里记录了明文操作凭证
配置文件中的 secrets
application.yml/config.json中的明文密码- Dockerfile 中
ENV指令写了秘密值(会被分层缓存) docker-compose.yml中的环境变量直接填值k8s ConfigMap中的明文 (而不是使用 Secret 资源).npmrc/.pypirc中的仓库认证
我曾经接手一个项目,所有的云服务密码都写在一个 passwords.txt 文件里,放在项目的根目录。这个文件被 .gitignore 排除了,但部署脚本把它复制到了镜像里。嗯,Docker 镜像推到了公开的 Docker Hub 上。任何人都能 pull 那个镜像,然后 docker run --entrypoint cat 读出所有密码。
一张图看清明文 Secrets 的泄露路径
下面这张图总结了「明文 Secrets 从哪来、到哪去、怎么被拿到」。你可以把它当成一份自查清单。
总结一下:为什么明文 Secrets 是「底线问题」
这章讲的不是高级漏洞。不是 SQL 注入,不是 RCE,不是复杂的加密算法破解。
就是最基础的「不该出现的地方出现了」。但偏偏是这种低级问题,每年让无数公司付出惨痛代价。
- ☐ 所有代码仓库(包括私有库)中是否扫描过历史 commit?
- ☐ CI/CD 日志是否关掉了 debug 输出和秘密回显?
- ☐ Docker 镜像中是否残留
.env或config文件? - ☐ 生产环境日志是否对 secrets 字段做了 mask?
- ☐ 环境变量是否只在进程启动时注入,且对子进程做最小化传递?
记住一件事:秘密一旦以明文形式出现在磁盘、内存或网络包中,它就不再是秘密了。