bigywater.tech
Docker · 90

环境变量泄漏:docker inspect 与 /proc/pid/environ

用环境变量传密码到底安全吗?这篇用一个假的秘密值,逐个检查 docker inspect、exec、/proc、日志、命令行和其它容器能不能看到它,以及 unset 之后的痕迹,最后对比挂载文件的做法。

4 处能看到
环境变量里的秘密:docker inspect、docker exec env、/proc/1/environ、虚拟机里的 /proc
pop 抹不掉
进程内 os.environ.pop 后,/proc/self/environ 里仍能读到
文件挂载看不到
改成只读挂载文件,docker inspect、env、environ 里都没有秘密值

环境变量

实测 · 本机执行输出
  docker inspect(Config.Env):能看到
  docker inspect 整个输出:能看到
  docker exec 里 env:能看到
  容器里 /proc/1/environ:能看到
  另一个容器(同一个网络)里 env:看不到
  虚拟机里读 /proc/<容器主进程 PID>/environ:能看到
  docker events / docker logs / docker ps:看不到
  docker exec 起的后续进程继承环境变量:能看到

能运行 docker inspect 或 docker exec 的人可以直接读到环境变量,在虚拟机里也能从 /proc 读;没有权限的容器和日志里看不到。

命令行

实测 · 本机执行输出
  docker ps --no-trunc 的 COMMAND 列(命令行里带 --token=…):能看到
  docker top(命令行参数):能看到
  docker inspect 的 Args / Path:能看到
  docker events:看不到
  容器还在运行吗?running

把秘密写在命令行参数里更糟,docker ps --no-trunc 就能列出来。

进程内删除

实测 · 本机执行输出
  读到了,长度 21
  os.environ 里还有吗: False
  /proc/self/environ 里还有吗: True
  docker exec cat /proc/1/environ(进程自己 pop 之后):能看到
  docker inspect Config.Env(创建容器时的配置,与进程里是否 pop 无关):能看到

应用读完把变量 pop 掉只影响进程内的 os.environ;内核保留的启动时环境块(/proc/self/environ)和 docker 的配置都还在。

用文件

实测 · 本机执行输出
  docker inspect 整个输出:看不到;docker exec env:看不到;/proc/1/environ:看不到
  应用仍然读得到文件:能看到;docker inspect 里能看到文件的路径:True

只读挂载的秘密文件不出现在 docker inspect 的环境里,也不在 env 里;但仍然是「能进容器的人都能读」,所以它减少的是意外泄露面(日志、inspect 输出、环境转储),不是权限边界。BuildKit 的 secret mount(c8)是构建期的同类做法。运行期的专用方案(Swarm / Kubernetes secrets)我没有测。

分步演示

环境变量泄露
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Docker Desktop(Engine 29.8.2,容器跑在 Docker Desktop 自带的 Linux 虚拟机里,内核与宿主机的 macOS 不同);镜像为 linux/arm64;需要看虚拟机内部时用特权容器 + nsenter;计时用 time / date +%s%N,数字每次运行会有小幅抖动。秘密是假字符串 S3CR3T-demo-value-123;逐处检查是否包含它;虚拟机里的 /proc 用特权容器加 nsenter 读取(方法见 c19);文件挂载用本项目临时目录下的文件;实验后已删除容器和临时文件
    • 没有验证:compose 的 secrets、Swarm secrets、docker run --env-file 的痕迹(shell 历史里没有)、docker history 里 ENV / ARG 的暴露(见 c7)、日志里误打印环境变量的情形、各 Linux 发行版上 /proc 的 hidepid 设置
    京ICP备2026067502号-1京公网安备11010502063487号