コンテナセキュリティはベースイメージから始まります。
しかし、ここに落とし穴があります。
- 単純にベースイメージの「最新」バージョンにアップグレードするだけでは、アプリケーションが動作しなくなる可能性があります。
- 既知の脆弱性を抱えたままリリースするか、互換性の問題を修正するために何日も費やすかのどちらかを選択せざるを得ません。
- そして多くの場合、アップグレードする価値があるのかさえ不明です。
本稿では、ベースイメージの更新がなぜ見かけよりも難しいのかを探り、実際の事例を挙げながら、アプリケーションを壊すことなく安全かつインテリジェントなアップグレードを自動化する方法をご紹介します。
問題点:「ベースイメージを更新するだけ」— 言うは易く行うは難し
本稿を読んでいる方は、おそらく「コンテナを安全にする方法」のようなキーワードで検索されたことがあるでしょう。そして、AIが生成したあらゆる記事で最初に目にするのは、ベースイメージを更新するというものです。簡単そうに見えますよね?しかし、そう簡単ではありません。
ベースイメージはセキュリティの中心点です。ベースイメージに脆弱性が含まれている場合、アプリケーションもその脆弱性を抱えることになります。このシナリオを考えてみましょう。
コンテナイメージに対してスキャンを実行すると、高深刻度のCVEが発見されました。役立つ推奨事項は、ベースイメージをアップグレードすることです。素晴らしい、ランチ前には完了するでしょう。
⚠️ CVE-2023-37920 が ubuntu:20.04 で発見
深刻度: 高
修正済み: 22.04
推奨事項: ベースイメージのアップグレード…しかし問題が発覚します。
から安易にアップグレードすると ubuntu:20.04 to ubuntu:22.04、アプリケーションは機能しなくなります。
ベースイメージを更新する際のいくつかの例と、実際に何が起こるかを見てみましょう。
例1: アップグレード後に動作しなくなるDockerfile
初期Dockerfile:
FROM python:3.8-buster
RUN apt-get update && apt-get install -y libpq-dev
RUN pip install psycopg2==2.8.6 flask==1.1.2
COPY . /appCMD ["python", "app.py"]チームは以下にアップグレードします:
FROM python:3.11-bookworm
RUN apt-get update && apt-get install -y libpq-dev
RUN pip install psycopg2==2.8.6 flask==1.1.2COPY . /appCMD ["python", "app.py"]結果:
psycopg2==2.8.6より新しいバージョンに対するコンパイルが失敗しますlibpqヘッダーでbookworm.flask==1.1.2サポートしていませんPython 3.11ランタイム機能(非推奨のAPIが動作しなくなります)。- CIでビルドが失敗します。
- 開発チームは不満を抱き、ランチも台無しになります。
例2:微妙なランタイムバグを引き起こすベースイメージのアップグレード
オリジナル:
FROM node:14-busterCOPY . /app
RUN npm ci
CMD ["node", "server.js"]アップグレード先:
FROM node:20-bullseye
COPY . /app
RUN npm ci
CMD ["node", "server.js"]ランタイムの問題:
node:20より新しいOpenSSLバージョンを使用しており、厳格なTLS検証により古いaxiosの設定が機能しなくなります。- アプリは
UNABLE_TO_VERIFY_LEAF_SIGNATUREランタイム時にエラーをHTTPレガシーサービスへの呼び出しでスローします。
「latest」がなぜ落とし穴なのか
Dockerエコシステムでは、最新のタグやトップラインリリースを使用することが推奨されています。しかし、これは月曜日に動作していたアプリケーションが火曜日に突然失敗する、という事態を招くことがよくあります。これは、バグ修正に時間を費やすことで、頭痛の種、停止、開発の遅延を引き起こす罠となることがよくあります。
テスト済みのマイナーバージョンに固定することが解決策だと考えられがちですが、そう簡単ではありません。これは、常に新たなCVEを発見し続け、脆弱な状態に陥る可能性がある「セキュリティのモグラ叩き」ゲームに足を踏み入れることになります。
意思決定の麻痺:アップグレードすべきか否か?
セキュリティチームはアップグレードを推進します。
開発者は安定性を理由に難色を示します。
どちらが正しいのでしょうか? 状況によります。
しかし、その意思決定を理解するためには、すべての選択肢を検討する必要があります。これは、すべてのバージョン、セキュリティリスク、安定性リスク、および可用性を網羅した膨大なスプレッドシートを作成することを意味します。
それがどのようなものか見てみましょう。
これにより、複雑で、質の悪い、不可能な選択肢が残されます
- 古いイメージに留まり、脆弱性を受け入れる
- アップグレードしてアプリケーションを破損させ、本番環境のダウンタイムのリスクを負う
- 手動での互換性テストを試みる — 数日間の作業
手動アップグレードのワークフロー:
これを手作業で行う場合、以下のようになります:
- CVEを確認:
trivy image python:3.8-buster - 各CVEを調査します。アプリケーションのコンテキストで到達可能ですか?
- アップグレード候補を決定します
- 新しいイメージをテストします:
- ビルド
- 単体テストを実行します
- 結合テストを実行します
- 失敗した場合は、コードをパッチするか、ライブラリをアップグレードしてみてください。
- すべてのコンテナで繰り返します。
これは非常に手間がかかります。
現状維持のコスト
「壊れていなければ直すな」と考えるかもしれません。
しかし、パッチが適用されていないコンテナのCVEは、セキュリティ侵害の大きな要因です。「本番環境で稼働しているコンテナイメージの87%に、少なくとも1つのクリティカルまたは高深刻度の脆弱性がありました。」出典
人気のあるベースイメージには、既知の多くのエクスプロイトも存在します。
- Unzipパス・トラバーサル脆弱性(
CVE-2020-27350)は、何百万ものコンテナに何年も存在していました。 - Heartbleed (
CVE-2014-0160)は、公式の修正がリリースされた後も、レガシーコンテナに長く残っていました。 PHP-FPM RCE(CVE-2019-11043)は、細工されたHTTPリクエストを介してリモート攻撃者が任意のコードを実行することを可能にし、以下のコンテナベースイメージで非常に一般的でした。pre-installed PHP-FPMパッチが適用される前は
AI AutoFix機能がどのように役立つか
この正確なシナリオを解決するため、Aikido Securityはコンテナの自動修正機能を展開しました。私たち自身もこの課題に直面しているからです。
この機能は次のように動作します。Aikidoはコンテナの脆弱性をスキャンします。脆弱性が発見された場合(または、より可能性が高いのは発見された時)、いつものようにアラートを発し、ベースイメージを更新するよう促す代わりに、複数の選択肢を提供します。どのベースイメージのバージョンがどのCVEを解決するかを示す表を作成します。これにより、マイナーバージョンアップで高リスクのCVEのすべてまたは大部分が解消され、ベースイメージの適切なアップグレードであることが非常に迅速に確認できます。
アップグレードがマイナーな変更である場合、バージョンを上げるためのプルリクエストを自動的に作成できます。
これにより、何時間もの作業が削減されます
結論:
- コンテナのベースイメージのアップグレードは本当に困難です。
- 「ただアップグレードするだけ」というアドバイスは、複雑でリスクを伴うプロセスを過度に単純化しています。
- チームが慎重になるのは当然ですが、セキュリティと安定性のどちらかを選択する必要はありません。
- Aikidoのコンテナ自動修正は、お客様に代わって難しい作業を行うため、情報に基づいた意思決定が可能です。
- 次にベースイメージの脆弱性アラートを見たとき、パニックになることはありません。プルリクエストを受け取るでしょう。

