Skip to main content

JavaScriptおよびNode.jsのオープンソースプロジェクト向けDevSecOpsツール

著者

2020年11月24日

0 分で読めます

この記事では、オープンソースプロジェクトのメンテナーや開発者がDevSecOpsツールを活用して、セキュリティ態勢を強化するためのベストプラクティスを紹介します。

JavaScriptのオープンソースエコシステムでは、悪意のあるパッケージによるセキュリティインシデントや恐ろしい事例が後を絶ちません。オープンソースエコシステムの一員として、プロジェクトのメンテナーであれ利用者であれ、誰もが危険にさらされないように、オープンソースのセキュリティに十分な注意を払う必要があります。

以下で紹介するDevSecOpsツールとセキュリティプラクティスは、軽量なnpmプライベートプロキシ兼レジストリプロジェクトverdaccioと緊密に連携してきた、Snykでの私の経験に基づいています。具体的には、次の内容を取り上げます。

  1. 責任あるセキュリティ脆弱性開示ポリシーを採用し、セキュリティガイドラインの一部としてプロジェクトに明記する。

  2. セキュリティプロセスとセキュリティガイドラインを整備する。

  3. すべてのメンテナーと協力者が、GitHubとnpmレジストリの両方で二要素認証(2FA)を有効にしていることを確認する。

  4. gitのpre-commitフックを使用して、開発者がコミットやリポジトリへのプッシュ時にパスワードやシークレットを漏えいさせないようにし、データ侵害や機密情報の露出を防ぐ。

  5. オープンソースの依存関係のスキャンと修正を導入し、サードパーティのオープンソースパッケージに含まれる脆弱性を防ぎましょう。GitワークフローにSnykを統合すると役立ちます。

  6. Snyk Advisorを使ってnpmレジストリにある100万以上のオープンソースパッケージを検索・比較し、適切なnpmパッケージを選びましょう。

責任あるセキュリティ脆弱性開示ポリシーを採用する

責任あるセキュリティ脆弱性開示ポリシーがあれば、セキュリティ研究者やほかのユーザーがプロジェクトに影響する脆弱性を報告し、第三者の目に触れない非公開の議論を通じて対応を進められます。

非公開の議論によって、関係者全員、すなわちメンテナーとセキュリティ研究者が詳細な調査を行い、脆弱性のトリアージや概念実証、そして最終的な修正による脆弱性の解消に取り組めます。

修正が利用可能になり、適切な期間が経過したら、脆弱性を一般に開示できます。ユーザーはアップグレードしてセキュリティ修正を適用できるようになります。

このプロセスにより、プロジェクトとの事前調整なしに開示される脆弱性からユーザーを守ることができます。

責任ある脆弱性開示がなぜ重要なのか、詳しくは責任ある脆弱性開示を理解するをご覧ください。Snyk Security Research Teamは、オープンソースプロジェクトのメンテナー向けにプログラムを提供しています。チームと連携して脆弱性のトリアージや修正に取り組み、CVEの申請を支援します。このプログラムはNode.js、Java、.NET、Python、Ruby、PHPなど、多くのプログラミング言語のエコシステムで利用できます/。

セキュリティガイドラインを整備する

プロジェクトには、チームメンバー間でインシデント対応を行うためのセキュリティプロセスを整備し、セキュリティ研究者に対してセキュリティへの備えやポリシーを伝える仕組みが必要です。

以下の情報を用意しておく必要があります。

  1. プロジェクトのセキュリティポリシー。たとえば、どの脆弱性をセキュリティ上の問題と見なすか、またどのようなケースが脆弱性に該当しないか。

  2. 責任あるセキュリティ脆弱性開示ポリシー、または対応する既存プログラムへの参照。

  3. プロジェクトのセキュリティリーダーへの連絡先。security.txt仕様にある関連フィールドを採用することをお勧めします。

  4. シークレットの漏えいを防ぐ——APIキーやパスワードなどのシークレットは、簡単にソース管理や、一般公開されているnpmレジストリのパッケージに混入してしまう可能性があります。

上記の内容を効果的に伝えるため、プロジェクトの最上位ディレクトリにあるSECURITY.mdファイルに記載することをお勧めします。

すべてのプロジェクト協力者が2FAを有効にする

マルウェアに感染していない安全なプロジェクトのバージョンをリリースする役割を担うメンテナーや協力者は、自分たちのアカウントが侵害されないようにする必要があります。npmでは、eslint-scopeのセキュリティインシデントやmailparserのnpmパッケージなどで、すでに同様の事態が発生しています。

パッケージの侵害やマルウェアの埋め込みは、これまでにも発生しており、今後も起こり得ます。バックドアとは何かを詳しく読み、Node.jsで簡単に作成してnpmに公開できることをご確認ください。

アカウント乗っ取りやパッケージ侵害のリスクを最小限に抑えるため、以下を徹底してください。

  1. すべての協力者が、ソースコードリポジトリで二要素認証(またはほかの多要素認証方式)を有効にする。

  2. パッケージの公開権限を持つすべての協力者が、npmレジストリで二要素認証を有効にしていること。

  3. プロジェクトに既知のバックドアがないかテストすることもお忘れなく。

データ侵害と機密情報の露出を防ぐ

オープンソースプロジェクトの公開リポジトリを管理する際によくある問題は、パスワードやAPIキーなどのシークレット、その他の機密情報を誤って公開してしまいやすいことです。

オープンソースプロジェクトでも、社内のプライベートなインナーソースプロジェクトでも、こうした事態を何度も目にしてきました。シークレットの漏えいによる影響を受けないプロジェクトはありません。忘れないでください。gitはすべてを記録します。

gitフックを使用する

作業ディレクトリには、SCMやパッケージレジストリへのコミット対象から除外する.envファイルなどに、シークレットが含まれている場合があります。しかし、ミスは起こり得ます。そうした事態に備え、確実に防ぐための対策が必要です。

コミットを静的解析する便利なツールが数多くあります。pre-commit Gitフックを使えば、パスワードや機密情報をGitHubリポジトリにプッシュしようとしていないか確認できます。機密情報の検出を目的として設定した正規表現パターンに一致した場合、コミットは拒否されます。プッシュが多少遅くなるかもしれませんが、その価値は十分にあります。

たとえばGitGuardianなどのツールをCI/CDパイプラインでも使用し、コードや設定ファイルから機密情報が見つかった場合にビルドを中断することもできます。こうした事態を防ぐチーム共通のルールを設けることは、既存の開発ワークフローで不適切な操作を防ぐ効果的な方法です。

なぜ重要なのでしょうか?

  1. https://github.blog/2019-05-14-git-ransom-campaign-incident-report/

  2. https://about.gitlab.com/2019/05/14/git-ransom-campaign-incident-report-atlassian-bitbucket-github-gitlab/

パスワード漏えいを防ぐ:detect-secretsツール

npmのプライベートレジストリおよびプロキシサーバーとして使われているVerdaccio npmオープンソースプロジェクトのメンテナーや開発者が、パスワードや機密情報を漏えいさせないことは、セキュリティ上きわめて重要です。

私は、機密情報がソース管理に漏えいするのを防ぐツールを開発ワークフローに追加するPull Requestでの共同作業に参加しました。

「feat: prevent secrets from leaking to source control」というタイトルのGitHubプルリクエスト。detect-secretsの統合とセキュリティラベルについて記載されています。

Yelpのdetect-secretsプロジェクトを選んだ理由は、リポジトリ内のシークレットのマニフェストを柔軟に管理できることと、検出したシークレットを監査する全体的なアーキテクチャにあります。オフラインでシークレットのマニフェストを管理し、追跡や許可リストへの登録が可能なほか、gitリポジトリでユーザーが操作する際に予防策を適用できます。

動作モード:

  1. 予防策:シークレットがソースコード管理に追加されるのを防ぐため、ファイルを引数として受け取り、シークレットの有無を確認するdetect-secrets-hook実行ファイルが用意されています。シークレットが検出されると警告を表示し、処理を中断します。

  2. 監査と許可リスト登録のためのオフラインスキャン:前述の予防策が適用されるのはコミット時のみのため、シークレットが追加された時点から先の漏えいしか防げません。オフラインスキャンでは、gitリポジトリ内のすべてのファイルをスキャンして既知のシークレットのベースラインを作成し、誤検知なのか、削除して適切に無効化する必要があるシークレットなのかを監査できます。

2つの動作モードは互いに補完し合い、開発者のニーズに合わせて個別に導入できる柔軟性を備えています。

gitフックのツールとしてdetect-secretsを使う方法は、すべてのプロジェクトに適しているとは限りません。特にJavaScriptやNode.jsのプロジェクトでは、動作するPython環境が必要です。プロジェクトに支障がなければ、次の手順でインストールして使い始められます。

$ pip install --user detect-secrets

また、npmベースのJavaScriptおよびNode.jsプロジェクトで使う手順として、detect-secretsで機密情報の露出を防ぐ方法もご紹介します。

JavaScript開発者向けに予防的なpre-commit対策を導入するため、以下の2つのプロジェクト依存関係を使用します。

  • huskyを使うと、プロジェクトレベルのマニフェストとnpm依存関係を通じて、npmプロジェクトでgitフックを簡単に管理できます。JavaScript開発者が使い慣れたツールを使って、フックの管理を効率化できます。

  • lint-stagedを使うと、ステージングされたファイルに対してリンターやフォーマッターなどのタスクを実行できます。コミット時に、あらかじめ設定した要件に沿ってファイルを更新できます。

注:lint-stagedは任意ですが、JavaScriptプロジェクトで広く使われている依存関係です。

lint-stagedとhuskyの両方を開発依存関係として追加したら、pre-commitフックに必要な設定をプロジェクトのpackage.jsonに追加します。

"husky": {
   "hooks": {
     "pre-commit": "lint-staged"
   }
 },
 "lint-staged": {
   "linters": {
     "**/*.js": [
       "detect-secrets-hook --baseline .secrets-baseline"
     ]
   }
 }

これで、gitのソース管理にファイルを追加または更新すると、シークレット、パスワード、APIキーなどの機密情報がないか確認され、リポジトリへのコミット処理が停止します。

注:モノレポで、huskyとlint-stagedの依存関係が最上位ではなくネストされたディレクトリにインストールされている場合は、.git/ディレクトリに対応するため、lint-stagedの設定を更新する必要があります。

 "lint-staged": {
   "relative": true,
   "linters": {
     "**/*.js": [
       "detect-secrets-hook --baseline .secrets-baseline"
     ]
   }
 }

シークレットのベースライン

gitリポジトリ内のすべてのファイルにシークレットが含まれていないか確認するため、必要に応じてスキャンを実行します。

detect-secrets scan > .secrets-baseline

スキャンが完了すると、生成された出力を使って、コードベース全体で許可リストに登録されたシークレットのベースラインを作成できます。JSONの結果には、使用したすべてのプラグインのメタデータ、スキャンの実施日時、シークレットのハッシュ、シークレットが見つかったファイルの詳細が含まれます。

READMEなどのドキュメントにシークレットのような文字列が含まれている場合があります。実際のシークレットではないため、コミットしてソース管理に残しても問題ありません。一方、実際のシークレットが見つかり、安全に対処する必要がある場合もあります。対処後に新たにscanを実行すると、削除済みのシークレットを含まない新しいベースラインが生成されます。

コードベースで見つかったシークレットの修正をチームが進められるよう、このツールにはaudit機能があります。ベースラインファイルを確認しながら、テストファイル内のシークレットなどの誤検知か、ソース管理にすでに存在しており削除が必要な真陽性かを、ユーザーが対話形式で切り替えられます。

Snykを統合して、開発スピードとセキュリティを両立する

開発スピードとセキュリティを両立するには?

オープンソースプロジェクトのメンテナーや協力者は、プロジェクトにオープンソースパッケージを取り込むことがよくあります。さらに、時間とともに依存関係は増えていきます。次に追加する依存関係に脆弱性がないことを、どうすれば確認できるでしょうか?

Verdaccioチームは、SnykをGitHubリポジトリに統合するgitインテグレーションを作成しました。CLIでセキュリティテストを実行できる、完全にサポートされたgitワークフローを提供します。

6件のチェックが成功し、マージコンフリクトがなく、緑色の「Squash and merge」ボタンが表示されたGitHubのプルリクエストのステータス

Snykをすぐに使い始めたい方は、このガイドで、セキュリティ初心者からエキスパートを目指しましょう。さらに、1分35秒の動画でSnykの使い方を手早く学ぶこともできます。

Getting Started with Snyk: Import and Test a GitHub Repository

Snyk Advisorで最適なパッケージを選ぶ

Verdaccio npmプロジェクトでは、commanderなどの依存関係を利用しています。しかし開発者として、npmパッケージのcommanderが健全なプロジェクトかどうか、どうすれば判断できるでしょうか?

幸い、Snyk Advisorを使えば、100万以上のオープンソースパッケージを検索・比較し、プロジェクトのメンテナンス状況、人気度、コミュニティ、セキュリティ態勢など、判断に役立つ重要な要素を数値化できます。これらの情報をもとに、Snyk Advisorはパッケージの総合的な健全性スコアを提示します。

commander npmパッケージのSnyk Advisorダッシュボード。健全性スコア94/100と、人気度、メンテナンス状況、セキュリティ、コミュニティのグラフを表示。

Verdaccioはcookiesとcorsにも依存しています。これらのスコアはどうでしょうか?ぜひご自身で確認してみてください!

おわりに

まとめとして、オープンソースプロジェクトのメンテナーや、その開発に携わる開発者が活用できる、さまざまなDevSecOpsツールとセキュリティ対策を紹介しました。パスワードがソース管理に漏えいするのを防ぐことから、依存関係の脆弱性をテスト・監視すること、さらにSnyk Advisorを使って適切なnpmパッケージを選ぶことまで取り上げました。

この記事とあわせて、次のコンテンツもぜひご覧ください。

キャプチャー・ザ・フラッグを始めよう

オンデマンドのバーチャル入門ワークショップを視聴して、キャプチャー・ザ・フラッグの課題の解き方を学びましょう。