ククログ

株式会社クリアコード > ククログ > 提供しているコンテナイメージに関する脆弱性を簡単に確認できるようにする方法

提供しているコンテナイメージに関する脆弱性を簡単に確認できるようにする方法

クリアコードではログデータ収集ソフトウェアの1つであるFluentdの継続的な開発に参加しています。 Fluentdのコンテナイメージやエンタープライズにおける長期運用に適したLTS版のパッケージ(Fluent Package)を提供しているのもその成果の1つです。

本記事では、コンテナイメージの脆弱性の有無をGitHub Actionsを活用して簡単に確認できるようにする方法について紹介します。

コンテナイメージの脆弱性を確認する方法

昨今ではOSSのものから商用版のものまで、多種多様な脆弱性スキャナが提供されています。

OSSだとTrivyであったり、Grypeなどが有名です。 脆弱性スキャンを実施するためのコンテナイメージも公開されているので、比較的利用しやすいです。

例えば、RubyのコンテナをGrypeでスキャンしてみると次のような結果が得られます。

$ docker run --rm anchore/grype:latest ruby:3.4-slim
NAME           INSTALLED                FIXED IN     TYPE  VULNERABILITY     SEVERITY    EPSS           RISK   
login.defs     1:4.17.4-2               (won't fix)  deb   CVE-2024-56433    Low         5.1% (89th)    1.7    
passwd         1:4.17.4-2               (won't fix)  deb   CVE-2024-56433    Low         5.1% (89th)    1.7    
tar            1.35+dfsg-3.1                         deb   CVE-2005-2541     Negligible  1.8% (82nd)    < 0.1  
libc-bin       2.41-12                               deb   CVE-2018-20796    Negligible  1.7% (81st)    < 0.1  
libc6          2.41-12                               deb   CVE-2018-20796    Negligible  1.7% (81st)    < 0.1  
apt            3.0.3                                 deb   CVE-2011-3374     Negligible  1.5% (80th)    < 0.1  
...(途中省略)...
coreutils      9.7-3                                 deb   CVE-2017-18018    Negligible  < 0.1% (17th)  < 0.1  
bsdutils       1:2.41-5                              deb   CVE-2022-0563     Negligible  < 0.1% (4th)   < 0.1  
libblkid1      2.41-5                                deb   CVE-2022-0563     Negligible  < 0.1% (4th)   < 0.1  
liblastlog2-2  2.41-5                                deb   CVE-2022-0563     Negligible  < 0.1% (4th)   < 0.1  
libmount1      2.41-5                                deb   CVE-2022-0563     Negligible  < 0.1% (4th)   < 0.1  
libsmartcols1  2.41-5                                deb   CVE-2022-0563     Negligible  < 0.1% (4th)   < 0.1  
libuuid1       2.41-5                                deb   CVE-2022-0563     Negligible  < 0.1% (4th)   < 0.1  
login          1:4.16.0-2+really2.41-5               deb   CVE-2022-0563     Negligible  < 0.1% (4th)   < 0.1  
mount          2.41-5                                deb   CVE-2022-0563     Negligible  < 0.1% (4th)   < 0.1  
util-linux     2.41-5                                deb   CVE-2022-0563     Negligible  < 0.1% (4th)   < 0.1  
coreutils      9.7-3                                 deb   CVE-2025-5278     Negligible  < 0.1% (3rd)   < 0.1

コンテナに含まれるパッケージのバージョンと、含まれる脆弱性とその影響度が確認できます。

Fluentdのコンテナイメージ特有の事情

Fluentdで提供しているコンテナイメージは、ベースイメージとしてRubyのコンテナを採用しています。 このRubyのコンテナはDebian由来なので、脆弱性スキャナにかけると、元にしているイメージの脆弱性も まるっと検出されます。

そのため、実際にはFluentdとしては影響がない場合であっても、脆弱性スキャナにかけた結果をそのまま問題ありとして報告されるというケースが多々あります。

元にしているイメージの更新に追従すればよい場合もありますし、Fluentdのためにカスタマイズした 部分については個別に対処が必要なこともあります。

例えば、Fluentdのコンテナイメージでは、Rubyのコンテナイメージに含まれるデフォルトのgemを更新して 提供することがあります。 その場合、コンテナイメージには古いバージョンのgemと新しいバージョンのgemが含まれます。 仮に古いバージョンのgemに脆弱性がある場合、実際に使われるのが脆弱性の問題を含まない新しいバージョンのgemであったとしても、脆弱性スキャナによって古いバージョンのgemが検出されます。

したがって、次のような観点で問題の有無を切り分けることになります。

  • 元にしているコンテナイメージ由来の脆弱性なのかどうか
  • 元にしているどのレイヤーのコンテナ由来の脆弱性なのかどうか
  • Fluentd向けにカスタマイズした部分の脆弱性なのかどうか

GitHub ActionsのJob Summaryで結果を確認しやすくする

Fluentdのコンテナイメージは、GitHub Actionsを利用してビルドするようにしているので、 脆弱性に関しても定期的に確認できると便利です。

そこで、次のような方針で実現する例を紹介します。

  • 各種脆弱性スキャナの提供元によるActionsは使わない(GitHubが公式に提供しているものだけ使う)
  • パッケージの提供元が修正しない(won't fix)と判断した脆弱性は除いて表示する
  • 影響度が低いと脆弱性スキャナが判断しているものは除いて表示する
  • コンテナに含まれているgemで新旧バージョンが同梱されているものを表示する
  • スキャンした結果はGitHub ActionsのJob Summaryにまとめる

各種脆弱性スキャナでは、出力形式としてJSONをサポートしていたりするのでそれを活用することにします。

新旧gemを含む場合は次のようにGitHub Actionsのレシピに組み込むことで抽出できます。

steps:
  - name: Scan bundled gems
    run: |
      docker run --rm fluent/fluentd:(コンテナイメージの任意のタグ) gem list | grep "," >> $GITHUB_STEP_SUMMARY

パッケージの提供元が修正しない(won't fix)と判断した脆弱性と、脆弱性スキャナによって影響度が低いと判断されたものを除いて抽出してみましょう。 Grypeで実現するには次のようにGitHub Actionsのレシピに組み込むことで実現できます。

steps:
  - name: Scan container image
    run: |
      docker run --rm anchore/grype:latest fluent/fluentd:(コンテナイメージの任意のタグ) --ignore-states wont-fix --output json | jq --raw-output '
            (["NAME","INSTALLED","FIXED IN","TYPE","VULNERABILITY","SEVERITY"] | join(" | ") | "| " + . + " |"),
            (["---","---","---","---","---","---"] | join(" | ") | "| " + . + " |"),
            (.matches[]
            | select(.vulnerability.severity != "Negligible")
            | "| \(.artifact.name) | \(.artifact.version) | \(.vulnerability.fix.versions[0] // "") | \(.artifact.type) | \(.vulnerability.id) | \(.vulnerability.severity)|")
            ' >> $GITHUB_STEP_SUMMARY

Grypeの場合、得られたJSONのvulnerability.severityにてNegligibleとマークされたものは影響度が低いとみなせるので、jqselect()で除外できます。

問題なく出力を加工できると、次のようなレイアウト結果がGitHub ActionsのJob Summaryとして得られます。

GitHub ActionsのJob Summaryに表示される内容のサンプル

他の脆弱性スキャナを利用する場合でも、JSONで得られた結果をフィルタすることで似たようなことはできるでしょう。

まとめ

今回は、コンテナイメージに関する脆弱性有無を簡単に確認できるようにする方法として、 コンテナイメージの脆弱性スキャナの結果をGitHub ActionsのJob Summaryに表示して結果を見比べやすくするやりかたを紹介しました。

実現したいことによっては、別のやりかたが適切ということもありますが、 関わっているプロジェクトでコンテナイメージを提供していて、その脆弱性をお手軽に確認したい機会があったら参考にしてみてください。

クリアコードはFluentdのサポートサービスを行っています。 プラグインの開発や、Fluent Packageへのアップデートのサポート等を提供しています。 詳しくはFluentdのサポートサービスをご覧いただき、お問い合わせフォームよりお気軽にお問い合わせください。

Fluentdに関する日本コミュニティ向けのXアカウントをはじめました。日々、Fluentdに関する情報を発信しております。 ぜひ @fluentd_jp をフォローしてください!