npm install 時にパッケージを静的解析してくれる「Socket」を使ってみた
こんにちは。
グローバルインストールしたツールが行方不明
オペレーション部のかわいです。
先日 Shai-Hulud がらみで npm のサプライチェーン攻撃対策を調べていたところ、Socket(socket.dev) というツールを知りました。
サプライチェーン攻撃は、例えば npm install でインストールされるパッケージそのものに悪意あるコードを仕込む攻撃です。
攻撃のよくある流れとしては以下のようなイメージです。
- 攻撃者が npm に悪意あるパッケージを公開する(例:既存パッケージへの混入)
- 気づかずにインストール
- インストール時にスクリプトが実行され、マルウェアが動く
- 被害が発覚して初めて脆弱性として登録される
例えば対策として npm audit で脆弱性チェックが考えられますが、公式ドキュメントにあるように、これは既知の脆弱性情報を取得する仕組みなので、4が起きるまで検出できません。Socket はこの2と3の間に割り込んで止める動きを取ります。
"The audit command submits a description of the dependencies configured in your project to your default registry and asks for a report of known vulnerabilities."
本記事では、備忘録がてらに Socket について書きます。
Socket とは?
Socket は、npm パッケージを静的解析してリスクを検出するツールです。GitHub App として導入する方法と、CLI から 使う方法があります。個人利用や小規模チーム利用なら無償利用できます。
npm audit が既知の脆弱性アドバイザリとの照合なのに対し、Socket はパッケージの振る舞いを見ます。
- インストール時に外部へ通信するスクリプトが含まれていないか
- コードが難読化(obfuscation)されていないか
- タイポスクワット(
react→reectのように、パッケージ名を巧妙に偽装する手法)ではないか - パッケージのメンテナが最近変わっていないか
どうやって検出してるの?
静的解析で、コードを実行せずにソースコードを解析する手法で検出しています。
"static analysis, which is a technique that involves analyzing source code without actually executing it"
たとえばネットワークアクセスの検出では、fetch()・Node.js の net・dgram・dns・http・https モジュールの使用を依存ツリー全体にわたってスキャンします。
特にインストールスクリプトを重視している点に関して、公式では以下のような数字が引用されています。
"research shows that 93.9% of malicious packages contain at least one install script"
(悪意あるパッケージの 93.9% にインストールスクリプトが含まれている)
また、タイポスクワットはダウンロード数の乖離(1000倍以上)を基準に判定しています。
"identifying similar package names with vastly different download counts (1,000x differential threshold)"
コード解析に加え、メンテナの行動パターンも見ています。新しいメンテナが publish 権限を取得した、異常なバージョンリリースが行われた、といった変化も検出対象です。
インストール方法
npm install -g socket
socket --version
1.1.85 # ブログ投稿時
簡易検証
socket npm install でパッケージをインストールしてみる
socket npm は npm をラップしたコマンドで、以下のように使用できます。
socket npm install lodash
_____ _ _ /---------------
| __|___ ___| |_ ___| |_ | CLI: v1.1.85
|__ | . | _| '_| -_| _| | token: (not set), org: (not set)
|_____|___|___|_,_|___|_|.dev | Command: `socket npm`, cwd: xxxxxx
√ Socket npm found no risks
added 1 package in 2s
Socket npm found no risks と出れば問題なしで、通常の npm install と同じようにインストールが完了しました。
リスクが検出された場合はインストール前に警告と確認プロンプトが表示されるとのこと。
"We only prompt for accepting the risk of installing packages for those that we alert on."
Socket for GitHub(PR への自動コメント)
CLI だけでなく、GitHub App としても使えます
GitHub リポジトリに Socket GitHub App を導入すると、Pull Request で依存関係が変更された際に自動でセキュリティ分析コメントが追加されます。
package.json や package-lock.json の差分を検出して、問題のあるパッケージを PR 上で知らせてくれます。
チーム開発では CLI よりこちらの方がレビューフローに馴染みます。
"package manifest files such as package.json, package-lock.json, and yarn.lock"
"Socket analyzes the package's behavior and leaves a comment if it is a security risk"
以下簡単に、公式ドキュメントに掲載されている実際の検出例を 2 つ紹介します。
例1)インストールスクリプト(protestware)
styled-components のバージョン 5.3.5 で、protestware(抗議目的のコード)を含むインストールスクリプトが追加されたケースで、これを検知した実績があるとのこと。
"Socket detected that the popular
styled-componentspackage decided to add a 'protestware' install script in version 5.3.5"
例2)テレメトリの収集
angular-calendar パッケージが依存関係として @scarf/scarf を追加し、リモートサーバーにテレメトリを送信していたケース。
"Socket detected that a newly introduced dependency,
angular-calendar, is collecting telemetry"
どちらも脆弱性としては登録されていない変化で、PR の段階で気づかなければ、そのままマージされていたかもしれません。
まとめ的な
socket を使用すると、脆弱性情報が登録される前のリスクを静的解析で拾い、インストール前にチェックしてくれます。
npm を使っているプロジェクトであれば、一度 socket を試してみるといいかもしれません。
【参考リンク】
完







