virtualenv activate.fish は、バックスラッシュが引用符の前に付いたパスまたはプロンプトからコマンドを実行します。
### 影響
`FishActivator` は `quote()` を定義していないため、`ViaTemplateActivator.quote` を継承し、これは `shlex.quote(string)` を返します。 その関数は、POSIX の `sh` のルールに従っており、シングルクォート内のバックスラッシュはリテラル文字として扱われます。 fish は、シングルクォート内の `\'` をエスケープされた引用符として、`\\` をエスケープされたバックスラッシュとして解釈します。 そのため、引用符の前にバックスラッシュがある値の場合、リテラルの終了位置が `shlex.quote` が指定した位置と異なり、その後のコマンド置換が展開されます。
環境変数は `set -gx VIRTUAL_ENV` に到達し、`--prompt` または `VIRTUALENV_PROMPT` は `set -gx VIRTUAL_ENV_PROMPT` に到達します。 `--prompt "x\'\$(touch PWNED)'\'"` の場合、生成される `activate.fish` には次の内容が含まれます。
```fish
set -gx VIRTUAL_ENV_PROMPT 'x\'"'"'$(touch PWNED)'"'"'\'"'"''
```
`source bin/activate.fish` を実行すると、`touch PWNED` が実行され、fish はエラーを表示しません。 ディレクトリ名として同じ内容が `VIRTUAL_ENV` を通ると、同様の結果になります。 `--prompt .` は、現在のディレクトリ名を指定するため、他の人が名前を付けたディレクトリ内で virtualenv を実行するだけで、この問題が発生します。 バックスラッシュがない場合、この内容は何も実行されず、bash でも同様です。
virtualenv は、デフォルトで `activate.fish` を生成します。 攻撃者は、環境変数またはプロンプトに影響を与える必要があります。 例えば、ブランチ、プロジェクト、またはジョブの名前を渡す CI ジョブやラッパーツール、またはクローンされたリポジトリまたは展開されたアーカイブ内のディレクトリなどです。
この問題は、`activate.fish` を同梱する 21.14.1 までのすべてのリリースに影響します。 21.7.13 での修正 (GHSA-p58f-9548-mpm2) は、プレースホルダーを引用符の外に移動しましたが、`shlex.quote` はそのままにしました。
### 修正
21.14.2 で修正されました。 `activate.fish` は、fish が解釈するバックスラッシュとシングルクォートをエスケープするように変更されました。 そのため、上記の例では何も実行されず、指定されたプロンプトが表示されます。 修正: https://github.com/pypa/virtualenv/commit/3bddeaf8d02c3ee7f576503efb082f8f494cfcab
### 対策
バックスラッシュを含むパスやプロンプトを持つ環境を作成しないでください。また、ご自身で作成していない `activate.fish` ファイルを使用する前に、内容を必ず確認してください。
### 謝辞
GitHub Security Lab の Kevin Stubbings 氏(@Kwstubbs)がこの問題を報告しました。
影響を受けるパッケージ:
- pip (Python) virtualenv: 影響を受けるバージョンは 21.14.1 以下、修正は 21.14.2 で行われました。