「Webには時代遅れで脆弱性のあるJavaScirptライブラリで溢れていることが研究により明らかに」という記事のとおり、世の中には脆弱性のあるJavaScriptライブラリを使った多くのウェブサイトが存在します。
IPAが公開している「安全なウェブサイトの作り方」には脆弱性が修正されたバージョンのライブラリを使用する。
と記述があったり、「OWASP TOP10 2017 (日本語版)」にも既知の脆弱性のあるコンポーネントの使用
を避けるように、と脆弱性のあるライブラリを使用しないよう注意喚起されています。
脆弱性のあるライブラリを使用しているか調べることができるRetire.jsを紹介します。
すべての脆弱性を防げる保証は無いので、あくまで自己責任でお使いください。
Retire.jsとは
Retire.jsは上の画像のようにCLIなどで実行することができる脆弱性のあるJSライブラリを検出するツールです。
Retire.jsのページにはThe goal of Retire.js is to help you detect the use of JS-library versions with known vulnerabilities.
と記述されています。
拙い訳ですが、「Retire.jsは脆弱性があることがわかっているJSライブラリを検知する補助を行うことを目的としています。」という意味です。
Retire.jsのページにRetire.jsが検知する脆弱性の一覧が掲載されています。
Retire.jsの使い方
使用方法はRetire.jsのGitHubに掲載されています。
npmでインストールしてCLIやgulp・gruntで実行することができます。
ChromeやFirefoxのエクステンションも提供されています。
CLI
まずはnpmのretire.jsを使用しコマンドラインから実行する方法を紹介します。
gulpから実行したい方やChromeやFirefoxのエクステンションで実行したい方は読み飛ばして下さい。
インストール
npmでretireというパッケージをインストールする必要があります。
Retire.jsをローカルにインストールせずに使いたい方は後述があるのでインストール手順は読み飛ばして下さい。
$ npm install -g retire
$ npm install --save-dev retire
調べたいプロジェクトの直下に移動して実行します。
$ retire
// package.jsonのscriptsに以下を追記
{
"scripts": {
"retire": "retire"
}
}
// CLIで実行
$ npm run retire
脆弱性のあるライブラリがある場合、以下のような内容がコンソールに表示されます。
以下はlodash 1.0.2に脆弱性があるのを検知した例です。
{package.jsonに記載されているname} 0.0.0
↳ lodash 1.0.2
lodash 1.0.2 has known vulnerabilities: severity: low; summary: Prototype pollution attack; https://hackerone.com/reports/310443
npmのバージョン5.2以上をお使いでローカルにインストールせずに使いたい方はnpxを使って実行することができます。
npxについては「npm 5.2.0の新機能! 「npx」でローカルパッケージを手軽に実行しよう」に詳しく紹介されています。
$ npx retire
gulp
gulpのタスクとして定義して実行することも可能です。
gulpについては「Gulp.js入門」をご覧ください。
Retire.jsのGitHubに掲載されている例を元に紹介します。
gulpで実行する場合もretireをnpmでインストールする必要があります。
gulpfileに以下のようなretireというタスクを書きます。タスク名は任意なのでお好きな名前に変更してください。
const gulp = require('gulp');
const spawn = require('child_process').spawn;
const gutil = require('gulp-util');
gulp.task('retire', function() {
var child = spawn('retire', [], {cwd: process.cwd()});
child.stdout.setEncoding('utf8');
child.stdout.on('data', function (data) {
gutil.log(data);
});
child.stderr.setEncoding('utf8');
child.stderr.on('data', function (data) {
gutil.log(gutil.colors.red(data));
gutil.beep();
process.exit(1);
});
});
Retire.jsのGitHubに掲載されているコードとの違いはprocess.exit(1)
で異常終了させているところです。こうすることでnpm-scriptsで複数タスクを実行する場合に異常終了したら以降の処理を行わないように制御することができます。
CLIに比べてgulpにすることのメリットは、脆弱性のあるライブラリがあった場合の処理を追加できるところです。
上記のgulpタスクの場合だと、gutil.colors.red(data)
でコンソール上のメッセージを赤く表示します。
Chrome・Firefoxエクステンション
ChromeやFirefoxのエクステンションとしても使うことができます。
以下からダウンロードしてお使いください。
こちらは他の開発者が開発したウェブサイトを検査するときにも使えます。
例えば、Wikipediaでは以下のような結果が出ました。
応用例
筆者が実際行っている応用例を紹介します。
公開前にチェックする
pre-pushやpre-commitと組み合わせれば、git commit
やgit push
したときに脆弱性のあるライブラリがあればコミットやpushを行わないように制御することができます。
{
"scripts": {
"retire": "retire"
},
"pre-commit": ["retire"]
}
package.jsonに記載されているライブラリだけチェックする
Retire.jsはデフォルトではnode_modules以下もすべて検査します。
package.jsonに記載されたライブラリだけ検査したい場合は-p
オプションを付けて実行します。
$ retire -p
gulp.task('retire', function() {
// 第二引数の配列にオプションを指定する
var child = spawn('retire', ['-p'], {cwd: process.cwd()});
child.stdout.setEncoding('utf8');
child.stdout.on('data', function (data) {
gutil.log(data);
});
child.stderr.setEncoding('utf8');
child.stderr.on('data', function (data) {
gutil.log(gutil.colors.red(data));
gutil.beep();
process.exit(1);
});
});
CIで実行する
GitHubとjenkinsやCircle CIなどCIツールを連携させて、pushされたときときに実行することも可能です。
GitHubとjenkinsの連携については「GithubからJenkinsへのServer Hook」や「Jenkinsでプルリクエストをビルドする」を参考にしてください。
まとめ
- 簡単に脆弱性のあるライブラリの使用を検出できる
- コミット前やデプロイ前に検査することで脆弱性のあるライブラリの使用を防止することができる
- 世の中のウェブサイトの脆弱性の検査をすることができる(悪用厳禁!)
- すべての脆弱性を防げるかはわからないので、これだけに頼らないこと!
# 参考
- Retire.js
- RetireJS/retire.js
- npm 5.2.0の新機能! 「npx」でローカルパッケージを手軽に実行しよう
- pre-push
- pre-commit
- GithubからJenkinsへのServer Hook
- Jenkinsでプルリクエストをビルドする
最後までお読み頂きありがとうございました。
不備や質問はコメント欄かTwitter(@shisama_)などでご連絡ください。