devcontainers / devcontainers/cli

Dotfiles install script interpolates targetPath/repository unquoted: paths with spaces break git clone/cd

オープン
#1,283 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る
主要言語
TypeScript
スター
3k
フォーク
457
平均マージ
13時間 17分
マージ済み PR(30日)
6

説明

## Summary

`installDotfiles()` interpolates `${targetPath}` and `${repository}` into a generated POSIX shell script **without quoting**, while environment-variable values in the very same script *are* escaped through `quoteValue()`. Any user-configured dotfiles path containing spaces (or other shell metacharacters) breaks the script via word splitting — `git clone`, `[ -e ]` and `cd` all operate on the wrong words — producing confusing failures during container start.

## Location

- File: [`src/spec-common/dotfiles.ts`](https://github.com/devcontainers/cli/blob/33073dbaba2545c51b4f8396e179c18231e80124/src/spec-common/dotfiles.ts)
- Function: `installDotfiles`
- Unquoted interpolations: lines 46, 48 (`[ -e ${targetPath} ]`, `git clone … ${targetPath}`, `cd ${targetPath}`) and the same pattern at 77–79; also line 90 (`ls -d ${targetPath}/.*`)
- Contrast: lines 33–35 + `quoteValue()` (124–126) deliberately single-quote-escape every environment value passed into the same script

```ts
// env values are quoted...
const allEnv = Object.keys(dockerEnvAndSecrets)
.reduce((env, key) => `${env}${key}=${quoteValue(dockerEnvAndSecrets[key])} `, '');
...
await shellServer.exec(`# Clone & install dotfiles
...
[ -e ${targetPath} ] || ${allEnv}git clone --depth 1 ${repository} ${targetPath} || exit $?
echo Setting current directory to '${targetPath}'
cd ${targetPath}
...`);
```

## Problem

`targetPath` is user-configurable (`dotfiles.targetPath`, see `ResolverParameters` in `devContainers.ts`; default `'~/dotfiles'`) and flows verbatim into the script. For a value containing whitespace, e.g. `/home/user/My Dotfiles`, the generated lines become:

```sh
[ -e /home/user/My Dotfiles ] || git clone --depth 1 /home/user/My Dotfiles || exit $?
cd /home/user/My Dotfiles
```

which word-split into `[ -e /home/user/My` and `Dotfiles ]`, a two-argument `clone` invocation with a stray `Dotfiles` argument, and a two-directory `cd`. The result is a failed or mis-cloned install with opaque shell errors rather than either success or a clear message. The same applies to `repository` if it contains characters interpreted by the shell.

Note that naive quoting cannot simply be added around `${targetPath}` for the *default* value, because `~/dotfiles` currently relies on unquoted tilde expansion — so the fix needs to handle tilde explicitly (e.g. expand to `$HOME` in TypeScript, or emit `"${HOME}/dotfiles"`), which is presumably why the current code avoids quotes.

## Trigger / Reproduction

Static analysis finding — not confirmed by execution; derived from the template literals at `main` (`33073dba`):

```jsonc
// devcontainer.json / CLI option
"dotfiles": {
"repository": "https://github.com/user/dotfiles.git",
"targetPath": "/home/user/My Dotfiles"
}
```

Run `devcontainer up` with dotfile installation enabled → the generated script splits words at the space and the install fails mid-way.

## Expected Behavior

Values interpolated into the shell script should be quoted/escaped consistently with how env values already are (`quoteValue`), with tilde handled explicitly so the default `~/dotfiles` keeps working.

## Actual Behavior

Unquoted expansion; paths with spaces (or glob/metacharacters) are split by the shell and every downstream command misbehaves.

## Impact

Any non-trivial `dotfiles.targetPath` silently corrupts the install script. Because the surrounding code already goes to the trouble of safely quoting environment values, this looks like an oversight rather than a constraint, and it produces hard-to-diagnose failures during dev-container startup.

## Suggested Direction

Emit `TARGET_PATH`/`REPO` as properly quoted assignments (reusing `quoteValue`), convert a leading `~/` to `$HOME/` before quoting, and reference `"$TARGET_PATH"` throughout the script. A unit test exercising a `targetPath` with a space would prevent regressions.

コントリビューションガイド

コントリビューションガイドを開く

調査の方向性

src/spec-common/dotfiles.ts の installDotfiles から始めて quoteValue を読み、次に devContainers.ts の ResolverParameters を調べて targetPath のデフォルト値を理解します。スペースを含む targetPath の単体テストを追加し、生成されたインストールスクリプトがパスを保持し、デフォルトのチルダパスを処理し、dotfiles のインストールを正常に完了することを確認します。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
shell, typescript
領域
cli
issue の種類
バグ
難易度
3/5
見積もり時間
1〜2日
活発さ
活発
明瞭さ
明確に書かれている
初心者へのやさしさ
78/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。