信頼できないソフトウェアと、どう付き合うか
そのコマンド、本当に信頼しているだろうか
Webフロントエンド開発では npx が良く使われていますよね。インストール不要で一発でコマンドを実行できて便利だと思います。
MCP サーバーや AI 関連ツールも同じ配布形態が多くて、 npx のほかにもPythonを呼びだす uvx や pipx が使われることも。
Web上に書かれているこれらのコマンドを実行するとき、なにをどこまで信頼しているのかが曖昧になりがちです。
開発者を信頼しているのか、プラットフォームを信頼しているのか、評判を信頼しているのか、じぶんのコンピュータの防御を信頼しているのか。
安全だと錯覚してしまう
インターネット老人会の話になりますが、昔はアプリストアのようなものはなく、アプリケーションが配布されているサイトに訪問してダウンロードやインストールをしていました。窓の杜とかの配布サイトを使うこともありましたよね。うっかりウイルスを踏んでしまった経験は誰しもあると思います。
そんな時代を経て、
現代では、一般利用者向けには、アプリストアが当りまえになっています。
Apple App Store / Google Play Store などです。
プラットフォームによってまちまちですが、特有の審査があり、レビューがあり、アプリケーションは署名され、実行はサンドボックス化された環境で行なわれます。
しかし NPM や PyPI はアプリストアでは無いです。
ほかの各種プラグインマーケットプレイスも、サービスによっては注意が必要です。
利用者のOSによる権限分離
何を実行するにしても、rootではなくユーザー権限なら被害が限定されるから大丈夫かっていうと、そんなことは無いです。
OSの権限分離は依然として大事で、root権限であれこれ実行するよりもユーザー権限のほうがいいことは間違いありません。しかし、現代の現実では、ユーザー権限だったとしても侵害されると甚大な被害があります。
今のユーザー権限の現実
- SSH keys
- API keys
- クラウド資格情報
- プライバシー、個人情報
ユーザー権限に「致命的なもの」が集まりすぎています。
NPM(npx)には権限分離の機能はありません。実行したフォルダの外にある、上記のような致命的なシークレットも自由に読める権限が実際にはあります。
SSHキーを盗まれてGitHubにアクセスされてしまったり、APIキーを盗まれて大事なデータベースを侵害されるようなシナリオが成り立ちます。
アプリストアではないアプリのあやうさ
NPMや各種のプラグインプラットフォームは、悪意とは無関係に、誰でも作ったものを公開できる仕組みになっています。
また、実行したつもりが無くても、 npm の postinstall script のように、インストールするだけでも何か処理を実行できる仕組みもあります。
危険が伴いますが、いちいちコードをチェックするようなことも、やってられません。
多くの利用者が、たとえばダウンロード数などの指標をみて、信頼をショートカットする作業を日々やっているはずです。
現実的な防御
あやういコードの実行を完全になくすことは現実的にはできないので、多層的な防御策が大事になってきます。
いくつか紹介します。
登場したばかりのアプリやバージョンを使わない
- pnpm の作者が提唱する「リリース直後のパッケージ利用を避ける」という考え方
- npx / pipx にそういった機能は無く常に最新版が実行される点に注意。
インストール時にコードを走らせない選択
npm の ignore-scripts などを設定。利便性は落ちる。
シークレットをディスクに置かない
.env ファイルは便利だが、ユーザー権限で動作する悪意のあるソフトウェアから容易に読みとられる可能性があります。
利用する場合、開発環境用など限定的に使うのがいいです。
~/.ssh にあるSSHキーも同様に、容易に読み取られる可能性があります。
1Password や Bitwarden などのパスワードマネージャーを使うと、こういったシークレットをディスクに置かない運用ができます。
- SSH Key:
- パスフレーズを設定する
- 1Password / Bitwarden の SSH Agent 機能を使う
- API Key:
- ローカルファイルに置く場合、権限をしぼる
- 1Password / Bitwarden の CLI で環境変数を実行時注入する
- その他、暗号化ソリューション
Dev Container などの隔離環境で試す/実行する
信頼できないアプリケーションを実行する場所をサンドボックス化。
コンテナ環境などで、SSHキーなど重要なシークレットにアクセスできないサンドボックスを自分で用意して、そのなかで信頼できないソフトウェアを走らせる。
サービス側で多要素認証を設定する
ベタだけど、多要素認証も依然として効果的です。
シークレットが侵害されても大丈夫なように備えましょう。
まとめ
開発者としては「信頼できないソフトウェアを実行しない」世界には戻れない
- どこまで信頼するのか、前提を考える
- 信頼しすぎない
- 影響範囲を小さくする
以上
ちょっと株式会社(chot-inc.com)のエンジニアブログです。 フロントエンドエンジニア募集中! カジュアル面接申し込みはこちらから chot-inc.com/recruit/iuj62owig
Discussion