Skip to main content

Non-upgradable dependencies

Need

Explicitly declare and manage dependencies in the source code to ensure upgradability and avoid potential security vulnerabilities.

Context

  • Usage of Scala 2.13.1 for developing scalable and high-performance applications
  • Usage of JDBC for connecting and interacting with relational databases
  • Usage of Anorm for type-safe database access in Scala
  • Usage of Ehcache for caching data in Java applications
  • Usage of ws for WebSocket communication
  • Usage of webjars-play for managing web assets in a Play Framework application
  • Usage of Bootstrap version 3.3.7-1 from org.webjars for front-end web development

Description

Non compliant code

name := "MyApp"

version := "1.0"

lazy val root = (project in file(".")).enablePlugins(PlayScala)

scalaVersion := "2.13.1"

libraryDependencies ++= Seq(
jdbc,
anorm,
ehcache,
ws,
"org.webjars" %% "webjars-play" % "2.8.0-1",
"org.webjars" % "bootstrap" % "3.3.7-1"
)

resolvers += "scalaz-bintray" at "https://dl.bintray.com/scalaz/releases"

The above code is an example of a build.sbt file in a Scala backend application that uses the Play framework. The libraryDependencies section is where you declare the dependencies for your project.

This code is vulnerable because it does not specify the exact versions of the dependencies it uses. Instead, it uses the %% operator to automatically fetch the latest version of the dependency that is compatible with the Scala version. This means that different developers, or even the same developer at different times, may end up using different versions of the same library without realizing it, leading to unpredictable behavior and hard-to-diagnose bugs.

Moreover, the code also uses the resolvers setting to add an additional repository, "scalaz-bintray". This is risky because it allows code from an external source to be included in the project, without any guarantee that this code will not change or disappear in the future.

Finally, the code does not include any mechanism to lock the versions of the dependencies, meaning that even if the developer specifies a version, there is no guarantee that this version will be used in all environments where the code is run.

To fix this vulnerability, each dependency should be declared with an explicit version, and a dependency lock file should be used to ensure that these versions are used consistently across all environments.

Steps

  • Explicitly declare all dependencies in the build file with their respective names and versions.
  • Avoid copying dependencies directly into the repositories.
  • Regularly update the dependencies to their latest versions to ensure they are upgradable.

Compliant code

name := "MyApp"

version := "1.0"

scalaVersion := "2.13.1"

lazy val root = (project in file(".")).enablePlugins(PlayScala)

libraryDependencies ++= Seq(
jdbc,
anorm,
ehcache,
ws,
"org.webjars" %% "webjars-play" % "2.8.0-1",
"org.webjars" % "bootstrap" % "3.3.7-1"
)

resolvers += "scalaz-bintray" at "https://dl.bintray.com/scalaz/releases"

The above code is a build file for a Scala application using the Play framework. It specifies the application's dependencies, but some of them are not explicitly declared with their respective names and versions. This is a vulnerability because it can lead to the use of outdated or insecure versions of dependencies.

To fix this vulnerability, all dependencies should be explicitly declared with their respective names and versions. This can be done by replacing the generic dependency declarations (like jdbc, anorm, ehcache, and ws) with specific versions. For example, instead of jdbc, use "com.typesafe.play" %% "play-jdbc" % "2.8.8" (replace "2.8.8" with the actual version you want to use).

Also, avoid copying dependencies directly into the repositories. Instead, declare them in the build file and let the build tool (like sbt for Scala) handle the downloading and linking of the dependencies.

Finally, regularly update the dependencies to their latest versions to ensure they are upgradable. This can help to avoid potential security vulnerabilities in outdated versions and also benefit from the latest features and improvements in the dependencies.

References