はじめに
フライウィールでプロダクト開発本部にて本部長を勤めている太田です。
今回の記事では、フライウィールにおける脆弱性対策の現状を、GitHub で利用できる脆弱性チェック機能である Dependabot アラート から分析して見えてきた知見を共有します。
サマリーとしては以下のようになります。
- Dependabotのアラート分析:この記事では、Dependabotのアラートを分析することで、脆弱性対策の現状を分析しました。また収集したデータを時系列でプロットしたり、様々な視点で比較することで、興味深い洞察を得ることができました。
- 自動更新効果:一部の言語では、Renovate という依存ライブラリの自動更新ツール を利用しています。言語間の比較することで、自動更新が脆弱性対策に対して効果的かつ持続可能な解決策を提供している可能性が見受けられました。
背景 / 動機
私たちのエンジニアリングチームが毎日直面している課題の一つは、依存ライブラリにおいて検知された脆弱性を効率的に管理し、防御する方法を見つけることです。フライウィールでは コードを全て一つのリポジトリで管理するMonorepoという開発手法を採用しています。そのため、複数のプロジェクトの依存ライブラリや Renovate などのライブラリの自動更新の仕組みを一元管理できます。一方で、多数の依存によるバージョンコンフリクトやプロジェクト間での影響の調節など特有の複雑性もあり、全社的に取り組んでいく必要があります。
直近では脆弱性対策をチームとして取り組むために、以下のような活動を行っています。
- Dependabot アラート を使った、リスクの高い脆弱性の検知と対応
- 定例ミーティングにおける、検知された脆弱性の確認と当番制による割当
- Renovate を使った依存ライブラリ更新の自動化
ただそれぞれの活動がどの程度効果的なのかといった疑問に対しては明確な答えをもてていませんでした。そこで Dependabot アラートを取得し、脆弱性がどの様に解消されているか、アラートに言語ごとの違いはあるかなどを分析してみることで、示唆を得ることを目指しました。
データ
今回の調査では、GitHub の Dependabot で検知された脆弱性アラートを分析の対象としました。Dependabot のアラートは API を通じて取得可能ですが、どのプルリクエストによって問題が修正されたかは直接取得できません。このため、修正時刻とGit の履歴を基に推測するシンプルなスクリプトを書きました。Appendix に記載しています。
収集したCSVデータはGoogleスプレッドシートに取り込み、そこでの簡易的な可視化を通じて分析を行いました。
分析
対応者による分析
まずは解決された脆弱性アラートについて、統計を取りました。脆弱性を解決したプルリクエストの数を、ユーザーごとに集計してみると、3人のメンバーが脆弱性を解決するプルリクエストを半数以上作っていることが明らかになりました。脆弱性対策の負担が特定の人々に偏っており、持続可能性に若干の不安があります。また Renovate によって解決されている脆弱性の割合はそこまで大きくないように見えますが、Renovate の効果については後の章で詳しく掘り下げます。
ユーザー別修正プルリクエスト数の割合
全言語時系列データの分析
次に時系列データを分析し、最近のトレンドや脆弱性対策への影響を調査しました。
以下の図は検知された脆弱性の累計数(Detected)と、修正された脆弱性の累計数(Fixed)を示すグラフです。Detected と Fixed の差分である赤いエリアがその時点で修正されていない脆弱性の数を表しており、そこが常に0になっているのが理想的な状態です。
累計発見アラート数と累計修正済アラート数
脆弱性は一定のペースで検知され続けていますが、未解決の問題は徐々に減少し、全体として健全な状態にあると言えます。この背景には、定例での定期的な共有など、脆弱性対策に対するチーム全体の意識の高まりの影響が考えられます。
脆弱性が一気に解決されている箇所も見られますが、これは利用されていないコードの削除によるものが主になります。商用環境での脆弱性解決に直接寄与しているわけではありませんが、脆弱性アラートが存在する状態を常態化させないためにも、使われていないコードの削除が効果的であることを再認識しました。
言語別時系列データの分析
言語ごと(より正確には利用する依存パッケージを管理するパッケージマネージャーごと)に分析することで、更に自動化などの影響などが見て取れます。
npm (TypeScript, JavaScript)
npm における累計発見アラート数と累計修正済アラート数
まずは npm (TypeScript, JavaScript) を見てみましょう。ある時期から脆弱性が解決されるペースが急速にあがり、また検知される脆弱性の数も減っており、一定期間ほぼ0を達成できています。その原因はこの統計からだけでは断言できませんが、Renovate の導入により依存ライブラリがほぼ最新になるようにアップデートされるようになった時期と一致しており、新しい脆弱性が Dependbot により検知される前に修正されている可能性が有りそうです。
PyPI (Python)
PyPI における累計発見アラート数と累計修正済アラート数
PyPI (Python) では、依存ライブラリの更新は主に手動で行っています。特に直近において、脆弱性対策への意識の高まりから、ほぼゼロの状態を保っています。一方で、Python を利用するプロジェクトの数や利用方法の多様性の向上に伴い脆弱性が検知されるペースについては増加しています。その結果、脆弱性対策の持続可能性に関しては若干の課題が残るように感じます。
maven (Java, Kotlin, Scala)
maven における累計発見アラート数と累計修正済アラート数
maven (Java, Kotlin, Scala) では、階段状の修正数グラフから、複数のパッケージのバージョンが一度にあげられていることがわかります。これは、フレームワークの全体の更新をする際に、同時に複数のパッケージのバージョンを上げる必要がある為と推測されます。実際、弊社でフレームワークの更新をおこなう際には、依存関係を含む大規模な修正となり時間と専門知識を要することが多く、そこに課題感を持っています。
まとめ
今回の調査では、Dependabot のアラートを調査することで、チームとして脆弱性対策を健全に回せていることに対して自信が持てました。また「依存の自動更新によりパッケージが最新状態に保つことは、脆弱性対策を持続可能な形で継続して行っていく上で有用な手段の一つである」という仮説を支持する示唆を出すことができました。
おわりに
フライウィールでは、チームの生産性向上に情熱を注ぐエンジニア、脆弱性対策に真剣に取り組むエンジニア、そして「Believe in Data」のバリューに共感し、データに基づいた意思決定に興味のあるエンジニアの参加を歓迎しています。