环境变量存密码本质不安全,因其为明文且可被子进程、日志、调试工具等广泛暴露;应杜绝无意义export,改用systemd environmentfile、k8s secrets、vault或gpg内存解密等受控方案。

环境变量里存密码,本身不安全——它不是加密容器,而是明文、可读、可映射的一段内存。真正的问题不是“能不能放”,而是“放了之后,它会在哪些地方被意外暴露”。关键在于切断泄露路径,而不是依赖“别人看不到”这种假设。
别让敏感变量进入进程环境空间
环境变量一旦被 export,就自动注入整个进程树:子进程、日志上下文、调试工具、甚至 strace 都能捕获。所以第一步是拒绝无意义导出。
- 只在绝对必要时 export,例如应用启动前由 systemd 注入,而非 shell 脚本中写 export DB_PASSWORD=xxx
- 用局部变量替代:CONFIG_PATH="/etc/app/conf"(不加 export),仅当前脚本可用
- 检查是否误导出:运行 env | grep -i "pass\|key\|token",发现即 unset
用受控方式注入,而非硬编码或全局配置
/etc/profile、/etc/profile.d/*.sh 是高危区,禁止在此类文件中明文 export 密码。系统级配置应只管行为逻辑,不管密钥内容。
- 改用 systemd 的 EnvironmentFile=:创建 /etc/secenv,权限设为 600,属主 root:root,内容仅含 export 行;服务单元中指定
EnvironmentFile=/etc/secenv - 容器场景优先用 Docker Secrets 或 Kubernetes Secrets,它们在运行时挂载为只读文件,不进环境变量空间
- 若必须用环境变量,通过启动脚本动态加载:先校验文件权限,再 source,并立即 unset 临时变量
阻断常见泄露渠道
密码进了环境变量,就可能出现在 ps 命令、/proc/[pid]/environ、日志、core dump、甚至容器镜像层里。得提前堵住这些口子。
- 禁用命令行传参式启动:避免
./app --password=xxx,ps aux 一眼可见 - 关闭日志框架的自动上下文注入:Log4j 设置
disableJmx=true,Winston 禁用process.env自动采集 - 限制 /proc 访问:非 root 用户无法 cat /proc/*/environ(默认已限制,但需确认未被覆盖)
- 启用 core dump 过滤:在服务单元中加
LimitCORE=0,防止密码随内存转储落盘
替代方案优先于环境变量
最安全的方式,是根本不要让密码以明文形式出现在用户空间。
- 生产环境首选 HashiCorp Vault 或云 KMS:应用启动时按需获取短期 token,不缓存、不落盘
- 本地轻量级场景可用 GPG 加密文件 + 内存解密:脚本中用
gpg -d --no-tty secrets.gpg 2>/dev/null直接输出到管道,不写临时文件 - 硬件级保护(嵌入式适用):U-Boot 环境变量 AES 加密 + eFuse 存密钥,Flash 里永远只有密文











