プログラミング
PATHにチルダを使わないで
Don't Put Tilde In Your Path (disconnect3d.pl)
要約
シェル設定でPATH環境変数にチルダ(~)を使用する際、ホームディレクトリへの展開が期待通りに行われないという一般的な落とし穴について解説しています。これにより、PATHが文字通り `./~/.local/bin/` として解釈され、セキュリティ上の問題やコマンドの誤実行につながる可能性があります。著者は、`export PATH="$PATH:~/.local/bin/"` の代わりに `$HOME` を使用し、`export PATH="$PATH:$HOME/.local/bin/"` のように記述することを推奨しており、この設定ミスを確認する方法も提供しています。
全文翻訳
nononoエージェントのサンドボックスツールで遊んでいたところ、PATHエントリのサンドボックスが書き込めるもの:~/.local/bin/ という警告が表示され、怪しいと思いました。
つまり、`~/.bashrc` または `~/.zshrc` で `export PATH="$PATH:~/.local/bin/"` のように記述しても、チルダ(~)はホームパス(または$HOME)に展開されません。チルダからホームへの展開は、チルダが引用符で囲まれていない入力でのみ行われるためです。bashのドキュメントにも次のように書かれています:単語が引用符で囲まれていないチルダ文字('~')で始まる場合、引用符で囲まれていない最初のスラッシュ(...)までのすべての文字はチルダプレフィックスと見なされます。(...)Bashは、各変数代入を、':'または最初の'='の直後にある引用符で囲まれていないチルダプレフィックスについてチェックし、これらのケースでチルダ展開を実行します。(...)
したがって、PATHに追加されるのは `/home/<user>/.local/bin/` ではなく、`./~/.local/bin/` になってしまいます。
これを修正するには、`export PATH="$PATH:$HOME/.local/bin/"` のようにします。
引用符で囲まれていないバージョン `export PATH=$PATH:~/.local/bin` は、BashとZshでは実際に機能します。これは、チルダ展開が '=' の後や各 ':' の後の変数代入でも実行されるためです。しかし、それに頼るのは脆弱です。例えば、空白があると変数代入が壊れてしまいます。
この問題はここで確認できます:
$ ls -la
total 0
drwxr-xr-x@ 2 dc staff 64 Oct 2 13:37 .
drwxr-x---+ 105 dc staff 3360 Oct 2 13:37 ..
$ mkdir -p ./~/.local/bin/
$ printf '#include <stdio.h>
int main() { puts("hello"); }'>a.c; gcc a.c -o ./~/.local/bin/kek
$ PATH="~/.local/bin/" kek
hello
$ tree -f .
.├── ./~
│ └── ./~/.local
│ └── ./~/.local/bin
│ └── ./~/.local/bin/kek
└── ./a.c
4 directories, 2 files
ご覧のとおり、`kek`バイナリは`./~/.local/bin/`から見つかり実行されました。ホームディレクトリは一切関与していません。
PATHを確認する
この問題があるかどうかは、以下で素早く確認できます:
$ echo "$PATH" | grep -- '~'
または、各エントリを1行ずつ表示するには:
$ echo "$PATH" | tr ':' '\n' | grep '~'
~/.local/bin/
何も表示されなければ問題ありません。もし表示されたら、`.bashrc` / `.zshrc` / `.profile` を修正し、`~` を `$HOME` に置き換えてください。
ちなみに、nononoツールがこれについて警告してくれたことに感謝します。警告はもっと詳細にできたかもしれませんが(PRを送信予定です)。