Skip to main content
Scanning Practices
Scala: Dependency Management and Scanning for build.sbt

Scala: Dependency Management and Scanning for build.sbt

The Challenge

Aikido can find known vulnerabilities (CVE) in your Scala dependencies as well as malware and dangerous licenses being used by those dependencies.

How does Aikido find those dependencies and their transitive subdependencies?

In case of Scala we scan the build.sbt file for dependencies. It should be noted that build.sbt files might not contain exact versions for some of your dependencies. This can cause Aikido to not find the full range of risks in your application.

It's therefore recommended to use build.sbt.lock lockfiles that contain an exact version for each dependency as well as the subdependencies.

There are other reasons to use lockfiles besides making security scanning easier for Aikido:

  • Using a lockfile protects you against supply chain attacks via malicious packages. This kind of attack is becoming more popular

  • Using a lockfiles makes your build more predictable as everyone is using the exact same minor version of packages. Less chance of 'works on my machine'

  • Faster build times: no need for dependency resolution anymore

Example

Let's look at a recent case that highlights these challenges.

// 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 reported:

  • 3 Critical CVEs in Akka HTTP

  • 2 High-severity vulnerabilities in Spark

  • 1 Critical vulnerability in the Cassandra driver

After investigation, all turned out to be false positives. The scanner was checking against different versions than what was actually being used in production:

// 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

Solution: Add a lockfile

Use the SBT Dependency Lock plugin to generate a lockfile for your project.

Step 1: Add the SBT Dependency Lock Plugin

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

Step 2: Generate Lock Files

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

The resulting lock file (build.sbt.lock) explicitly defines all dependencies:

{
  "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"
}

Step 3: Enforce Locked Dependencies

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

Alternative Workaround: Container Scanning

While lock files provide excellent dependency control at the source level, container scanning offers another powerful approach to security validation. Since containers include the compiled artifacts, they represent the actual state of your production environment.

Benefits of Container Scanning

# 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

When to Use Container Scanning

Container scanning is particularly valuable when:

  • You need to validate production-ready artifacts

  • Your build process involves multiple stages

  • You want to verify the exact versions running in production

  • You need to scan both your application and its runtime environment

Container Scanning vs. Lock Files

Aspect

Container Scanning

Lock Files

When to verify

Post-build

Pre-build

What's checked

Compiled artifacts

Source dependencies

Accuracy

Production-exact

Development-exact

Integration

CI/CD pipeline

Development workflow

Best Practice: Use both approaches. While container scanning is valuable, it's most effective when used alongside lock files.