こんにちは。アプリケーション部の兼安です。
少し前に脆弱性検知のブログを書かせていただきました。
その時に作った検証用リポジトリでGitHubのDependabot
をONにしていたところ、2024年1月になってパッケージの脆弱性を検知してくれました。
偶然の産物ですがせっかくなので、脆弱性の検知から解消までの流れを書かせていただきます。
本記事のターゲット
- Pythonを使用した開発をされている方
- Pipfileによるパッケージ管理の経験がある方
- GitHubでのソース管理の経験がある方
- 脆弱性の検知と解消のノウハウを探されている方
GitHubのDependabotが通知してくれた内容
こちらの件名のメールが届きました。
xx
の部分は日付です。
[GitHub] Your Dependabot alerts for today Jan xx
このメールが2024年が1月12日から、毎日9時ごろに届いていました。
本文には脆弱性の内容が記載されていました。
jinja2
に脆弱性があるとのことです。
書かれているCVEで検索してみると、確かに脆弱性の情報がHITします。
対処法はjinja2
を3.1.3にアップデートすることのようです。
リンク先の脆弱性ページには、情報を公開した日付も書かれています。
NVD Published Date:
01/10/2024
メールが最初に届いたのが2024年が1月12日の9時です。
時差を考えると、情報が公開されてすぐに検知してくれたようですね。
なぜDependabotはメールを送ってくれたのか?
Trivyを使用して脆弱性検知とSBOM出力をやってみる - サーバーワークスエンジニアブログ
このブログを書く時にDependency graph
をONにするついでに、Dependabot
もONにしていたからですね。
それぞれの使用方法はGitHubのドキュメントに記載されています。
GitHubのリポジトリの設定画面で、Dependabot
がONになっているのを確認できます。
Dependency graph
も依存関係が表示されているので、ONになっているとわかります。
そして、Dependency graph
の画面上でも脆弱性の存在が確認できました。
素晴らしい。
jinja2
が2行表示されているのは、私がDependency graph
だけでなく、GitHub Actions+TrivyでSBOM出力して、それもDependency graph
に表示させているからです。
Trivyもきちんと今回のjinja2
の脆弱性を検知してくれています。
これまた素晴らしい。
脆弱性を解消してみる
では、ここから脆弱性を解消してみます。
ターゲットのリポジトリはPythonのFlaskを使用した非常に簡単なWebアプリケーションです。
PipfileとPipfile.lockの確認
パッケージは、Pipfile
とPipfile.lock
で管理しています。
まずは、Pipfile
を確認してみます。
[[source]] url = "https://pypi.org/simple" verify_ssl = true name = "pypi" [packages] flask = "*" [dev-packages] [requires] python_version = "3.11"
脆弱性が検知されたjinja2
の記述はありませんでした。
ということは、jinja2
を直接インストールしておらず、他のパッケージの依存関係としてインストールされていると予想されます。
次に、Pipfile.lock
を確認してみます。
以下の記述を見つけました。
よくよく見れば元のメールにもDefined in Pipfile.lock
と書かれていますね💦
{ (省略) "default": { (省略) "jinja2": { "hashes": [ "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852", "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61" ], "markers": "python_version >= '3.7'", "version": "==3.1.2" }, (省略)
default
の下にjinja2
が記載されています。
バージョンが3.1.2なので、問題はここですね。
ただ、これだけだと何のパッケージの依存関係としてインストールされているのかわかりません。
コマンドで依存関係を確認してみる
依存関係を確認するために、pipenv graph
コマンドを実行してみます。
$ pipenv graph
次の結果が確認できました。
Flask
に依存していることがわかります。
(省略) flask==3.0.0 ├── blinker [required: >=1.6.2, installed: 1.7.0] ├── click [required: >=8.1.3, installed: 8.1.7] ├── itsdangerous [required: >=2.1.2, installed: 2.1.2] ├── Jinja2 [required: >=3.1.2, installed: 3.1.2] │ └── MarkupSafe [required: >=2.0, installed: 2.1.3] └── Werkzeug [required: >=3.0.0, installed: 3.0.1] └── MarkupSafe [required: >=2.1.1, installed: 2.1.3] (省略)
脆弱性の大元のパッケージをアップデート
jinja2
は、Flask
の依存関係としてインストールされていることがわかりましたので、Flask
をアップデートしてみます。
$ pipenv update flask
ちなみに、pipenv update jinja2
としても、jinja2
はPipfile
に記載されてはいないので通りませんでした。
アップデートの結果、Pipefile.lock
のjinja2
のバージョンが3.1.3に変わりました。
割愛しましたが、Flask
のバージョンも少しあがっているのが確認できました。
{ (省略) "default": { (省略) "jinja2": { "hashes": [ "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa", "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90" ], "markers": "python_version >= '3.7'", "version": "==3.1.3" }, (省略)
大元のパッケージではなく、脆弱性あるパッケージ単体をアップデート
Flask
のバージョンがあがってしまうのを避けたい場合は、Pipfile
にjinja2
を書いて、pipenv update jinja2
で単体でアップデートかけるのもなくはないかなと思います。
この状態をずっと続けるかどうかは議論すべきとは思いますが。
[packages] flask = "*" jinja2 = "*"
Dependency graphで解消されたかを確認
この状態でGitHubのリポジトリにpushしてみると、 脆弱性が解消したことをDependency graph
で確認できました。
画像は、jinja2
が下の方に移動していたので、検索でjinja2
だけ絞り込んで表示しています。
先ほどjinja2
が上に表示されていたのあは、脆弱性があるバージョンだったからですね。
通知が来なくなったことを確認
この状態で翌朝様子をみたところ、脆弱性の通知メールが届かなくなったのを確認しました。
まとめ
- GitHubの
Dependabot
をONにすると、インストールしているパッケージに脆弱性がある場合にメールで通知してくれる - GitHubの
Dependency graph
をONにすると、インストールしているパッケージの依存関係と脆弱性を可視化できる - パッケージの脆弱性の解消は、
Pipfile.lock
やpipenv graph
で依存関係を確認して、アップデートすることで解消できる
検知機能を活用して、安全なアプリケーションを開発していきましょう。
サーバーワークスでは、開発プロセスの最適化を支援するサービスを提供しています。
兼安 聡(執筆記事の一覧)
アプリケーションサービス部 DS3課所属
2024 Japan AWS Top Engineers (Database)
2024 Japan AWS All Certifications Engineers
認定スクラムマスター
広島在住です。今日も明日も修行中です。