Hacktoberfest 2026:維護者為十月標記出來的 issue,仍然開放、適合新手。 瀏覽 Hacktoberfest issue

userEnvProbe (and --secrets-file) put container env values, incl. secrets, on the host `docker exec` argv

未關閉
#1,317 0 則留言 0 個 reaction 已指派 1 人 在 GitHub 檢視

維護者通常 1 天內回覆

@v-Kaniska244 已經在處理了。

開始於 2026年10月6日。

評估

難度
4/5
預估耗時
3-5 天
新手友好度
68/100
Issue 類型
缺陷
描述清晰度
描述清楚
活躍度
活躍
技術堆疊
docker, typescript
領域
cli, devops, security

研究方向

Start in src/spec-shutdown/dockerUtils.ts at toDockerExecArgs, then trace remoteEnv from probeUserEnv and the secrets merge in src/spec-common/injectHeadless.ts. Run the supplied Docker reproduction for both userEnvProbe and --secrets-file. Done means lifecycle hooks and devcontainer exec still receive their environment while secret values no longer appear in host docker exec argv.

由索引模型根據 Issue 內容生成。

描述

Summary

When userEnvProbe is enabled (the default, loginInteractiveShell), the CLI reads the container user's whole environment (cat /proc/self/environ) and passes every variable back to docker exec as a -e NAME=VALUE argument. This happens on every lifecycle hook (onCreateCommand, postCreateCommand, postStartCommand, …) and on every devcontainer exec.

So any secret that is already in the container's environment ends up in plaintext on the host process command line, where any local user can read it with ps. That includes secrets injected with runArgs: ["--env-file", …], containerEnv or an image ENV. Those variables are already part of the container's Config.Env, which docker exec inherits, so re-sending them on the command line gains nothing.

The --secrets-file feature has the same problem, even with "userEnvProbe": "none". Lifecycle commands merge the secrets into the exec env (const env = { ...(await remoteEnv), ...(await secrets) }), so each secret appears as -e NAME=VALUE on the host argv while the hook runs.

Where

On main (3e363f63a712d30a741174f6d1a7e75f47fe3fc1):

  • src/spec-shutdown/dockerUtils.ts toDockerExecArgs (~L400-415): Object.keys(env).forEach(key => execArgs.push('-e', ${key}=${env[key]}))
  • src/spec-common/injectHeadless.ts probeUserEnv (~L777-789, cat /proc/self/environ) feeds remoteEnv. runLifecycleCommand (~L518) merges remoteEnv and secrets into that env.
  • In the published 0.89.0 bundle (dist/spec-node/devContainersSpecCLI.js) the same logic is the minified function KN: r&&Object.keys(r).forEach(a=>g.push("-e",${a}=${r[a]})).
Repro (dummy values only)

@devcontainers/cli 0.89.0, Docker Desktop on macOS, image alpine:3.

mkdir probe && cd probe
umask 077
printf 'ARGV_PROBE_VAR=DUMMY_NOT_SECRET\n' > dummy.env
printf '{"image":"alpine:3","overrideCommand":true,"runArgs":["--env-file","%s/dummy.env"]}\n' "$PWD" > .devcontainer.json
devcontainer up --workspace-folder .
devcontainer exec --workspace-folder . sleep 6 &
sleep 3; ps -axww -o command | grep '^docker exec'

Observed (other values elided):

docker exec -i -u root -e HOSTNAME=… -e SHLVL=… -e HOME=… -e PAGER=… -e LC_COLLATE=… -e PATH=… -e LANG=… -e CHARSET=… -e ARGV_PROBE_VAR=DUMMY_NOT_SECRET -w /workspaces/probe <id> sleep 6
Arm docker exec argv contains ARGV_PROBE_VAR=DUMMY_NOT_SECRET Var visible inside the container
default userEnvProbe yes (1 process) yes
"userEnvProbe": "none" no (0) yes (inherited from Config.Env)

--secrets-file arm: config {"image":"alpine:3","overrideCommand":true,"userEnvProbe":"none","postStartCommand":"sleep 8"} with --secrets-file secrets.json containing {"SECRETSFILE_PROBE_VAR":"DUMMY_NOT_SECRET_2"}. While the hook ran, the host showed docker exec -i -u root -e SECRETSFILE_PROBE_VAR=DUMMY_NOT_SECRET_2 -w /workspaces/probe-secretsfile <id> /bin/sh -c sleep 8.

We found this in a real setup where Doppler secrets were injected with --env-file. Every secret showed up in the host process table during devcontainer up and devcontainer exec.

Suggested fix

Any of these, in order of preference:

  1. Pass variables by name, not by value. Use docker exec -e NAME (no =), so docker reads the value from the CLI process's own environment, and spawn the docker child with { ...process.env, ...env }. Values never appear on argv. This also covers --secrets-file and remoteEnv.
  2. Or use docker exec --env-file <tmpfile>, written mode 0600 and removed after the exec starts.
  3. At minimum, don't re-send probed variables whose value already equals the container's Config.Env value. docker exec inherits those, so dropping them changes nothing. Only the delta the login shell adds would remain (e.g. PATH), which is rarely sensitive.

Workaround for users: set "userEnvProbe": "none" and run commands that need the login environment through bash -lc. This does not help with --secrets-file.

主要語言
TypeScript
星號
3k
分支
462
平均合併
13 小時 28 分鐘
30 天內合併 PR
2

環境準備

在 Codespaces 中開啟

在瀏覽器裡用你自己的 GitHub 帳號啟動這個專案的開發容器。

  • 沒有 Dockerfile 或 Docker Compose 檔案
  • 沒有 Pull Request 範本
  • 閱讀貢獻指南

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

devcontainers/cli 的其他 Issue

查看 devcontainers/cli 的全部 Issue

相似的 Issue

更多 TypeScript Issue

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。