コンテンツにスキップ

Scala: build.sbt の依存関係管理とスキャン

Aikido は、Scalaの依存関係に含まれる既知の脆弱性(CVE)に加え、それらの依存関係が使用するマルウェアや危険なライセンスも検出できます。

Aikido はどのようにしてこれらの依存関係とその推移的な副依存関係(transitive subdependencies)を見つけているのでしょうか。

Scalaの場合、build.sbt ファイルをスキャンして依存関係を検出します。ただし、build.sbt ファイルには一部の依存関係について正確なバージョンが記載されていないことがある点に注意が必要です。これにより、Aikido がアプリケーション内のリスクを完全には検出できない場合があります。

そのため、各依存関係と副依存関係の正確なバージョンを含む build.sbt.lock のロックファイルを使用することを推奨します。

Aikido のセキュリティスキャンを容易にすること以外にも、ロックファイルを使用すべき理由があります。

  • ロックファイルを使用することで、悪意のあるパッケージによるサプライチェーン攻撃から保護されます。この種の攻撃は増加傾向にあります
  • ロックファイルを使用することで、全員が全く同じマイナーバージョンのパッケージを使用するためビルドがより予測可能になります。「自分の環境では動く」という事態が起きにくくなります
  • ビルド時間の短縮: 依存関係解決が不要になります

これらの課題を浮き彫りにする最近の事例を見てみましょう。

// Original build.sbt without lock files
libraryDependencies ++= Seq(
  "com.typesafe.akka" %% "akka-http" % "10.2.+",
  "org.apache.spark" %% "spark-core" % "3.+",
  "com.datastax.cassandra" % "cassandra-driver-core" % "latest.release"
)

Aikido は次のように報告しました。

  • Akka HTTP に Critical な CVE が3件
  • Spark に High レベルの脆弱性が2件
  • Cassandra driver に Critical な脆弱性が1件

調査の結果、すべて誤検知(false positive)であることが判明しました。スキャナーは、実際に本番環境で使用されているものとは異なるバージョンを照合していたのです。

// What the scanner thought was running
akka-http 10.2.0   // Vulnerable
spark-core 3.0.0   // Vulnerable
cassandra-driver 4.0.0  // Vulnerable
// What was actually running in production
akka-http 10.2.10  // Secure
spark-core 3.3.2   // Secure
cassandra-driver 4.15.0  // Secure

解決策: ロックファイルを追加する

Section titled “解決策: ロックファイルを追加する ”

SBT Dependency Lock プラグインを使用して、プロジェクトのロックファイルを生成します。

手順1: SBT Dependency Lock プラグインを追加する

// In plugins.sbt
addSbtPlugin("software.purpledragon" % "sbt-dependency-lock" % "1.5.1")

手順2: Lock Fileを生成する

// Run this command to resolve dependencies and generate lock files
sbt "dependencyLockWrite"

生成されるロックファイル(build.sbt.lock)は、すべての依存関係を明示的に定義します。

{
  "com.typesafe.akka:akka-http_2.13": "10.2.10",
  "org.apache.spark:spark-core_2.13": "3.3.2",
  "com.datastax.cassandra:cassandra-driver-core": "4.15.0"
}

手順3: ロックされた依存関係を強制する

// Run this command to resolve dependencies and validate against lockfile
sbt "dependencyLockCheck"

ロックファイルはソースレベルでの優れた依存関係管理を提供しますが、コンテナスキャンはセキュリティ検証のもう一つの強力なアプローチです。コンテナにはコンパイル済みの成果物が含まれるため、本番環境の実際の状態を表しています。

# Example Dockerfile showing what gets scanned
FROM openjdk:11-jre-slim
# Your compiled artifacts are here
COPY target/scala-2.13/your-app.jar /app/
COPY target/scala-2.13/lib/* /app/lib/
# These are the actual versions that will run in production
RUN ls -la /app/lib/
# akka-http_2.13-10.2.10.jar
# spark-core_2.13-3.3.2.jar
# cassandra-driver-core-4.15.0.jar

コンテナスキャンを使うべき場面

Section titled “コンテナスキャンを使うべき場面 ”

コンテナスキャンは特に次のような場合に有効です。

  • 本番対応の成果物を検証する必要がある場合
  • ビルドプロセスに複数のステージが含まれる場合
  • 本番環境で実行されている正確なバージョンを確認したい場合
  • アプリケーションとそのランタイム環境の両方をスキャンする必要がある場合
観点 コンテナスキャン Lock Files
検証タイミング ビルド後 ビルド前
チェック対象 コンパイル済み成果物 ソースの依存関係
正確性 本番環境と完全一致 開発環境と完全一致
統合 CI/CDパイプライン 開発ワークフロー

ベストプラクティス: 両方のアプローチを併用してください。コンテナスキャンは有用ですが、ロックファイルと組み合わせて使うことで最も効果を発揮します。