Programming

How to fix a CVE by overriding the version of a Spring Boot dependency

If you haven’t yet needed to override the version of a transitive dependency from Spring that has become vulnerable, you may be missing security scans to ensure your software isn’t vulnerable to the latest threats.

Occasionally, a new CVE (a vulnerability) pops up from the wild.

If it happens to be a dependency that Spring Boot uses and you’re affected, you should not wait for Pivotal to release a new version with the update. (since their updates are scheduled, whereas the library authors tend to be quick in releasing the fix)

These kind of dependencies – where it’s used by a library/framework you’re using – are called transitive dependencies. You depend on them, but not directly.

This post will cover how to apply the fix and confirm it is fixed.

Remember that not all CVEs affect you, you should factor in their severity and in which situations it is exploitable, sometimes the vulnerabilities are specific to an API method you’re not using.

Example of a CVE

Recently, Spring Boot WebFlux 3.2.4 was vulnerable to CVE-2024-29025 due to its dependency on the Reactor Netty library (which depended on the vulnerable netty-codec-http package).

To reproduce this issue, let’s write a Spring Boot application with this:

plugins {
    id("org.springframework.boot") version "3.2.4"
    id("io.spring.dependency-management") version "1.1.4"
    ...
}

dependencies {
    implementation("org.springframework.boot:spring-boot-starter")
    implementation("org.springframework.boot:spring-boot-start-webflux")
    ...
}

Now, at the time of writing the fixed Spring Boot version has already been released (3.2.5), but for the sake of demonstration let’s assume it hasn’t yet. How do we change the version of the Reactor Netty library to its fixed version?

Finding the version

Before changing the version, let’s see if we can spot it.

In Gradle, run gradle dependencies to view the whole dependency list, including the transitive ones. (on Maven, run mvn dependency:tree)

The output is huge even for just one Spring Boot dependency (“even if”, as if it’s not to be expected from Spring 😅).

By searching for netty-codec-http, we can see its version and where it comes from:

...
+--- org.springframework.boot:spring-boot-starter-webflux -> 3.2.4
|    +--- org.springframework.boot:spring-boot-starter-reactor-netty:3.2.4
|    |    \--- io.projectreactor.netty:reactor-netty-http:1.1.17
|    |         +--- io.netty:netty-codec-http:4.1.107.Final
...

Security scanners (such as Coverity and BlackDuck) already show the tree on their report, but it’s always good to have a way of confirming on our side.

Overriding the version

To override Spring Boot dependency versions, you set the “extra” property of that dependency with the version you want to override.

Consult Spring Boot’s reference site (this one is for 3.2.4, make sure you see yours) to see the right name of the property. In my case, it is from Netty, so it’s netty.version.

Anywhere on the top level of the build.gradle.kts file, add the following:

extra["netty.version"] = "4.1.108.Final"

On Maven, it looks like this:

	<properties>
		<netty.version>4.1.108.Final</reactor.version>
	</properties>

The output of gradle dependencies is now:

...
+--- org.springframework.boot:spring-boot-starter-webflux -> 3.2.4
|    +--- org.springframework.boot:spring-boot-starter-reactor-netty:3.2.4
|    |    \--- io.projectreactor.netty:reactor-netty-http:1.1.17
|    |         +--- io.netty:netty-codec-http:4.1.107.Final -> 4.1.108.Final
...

That arrow (->) indicates that the reactor-netty-http dependency has requested the “4.1.107.Final” version, but it will be resolved with 4.1.108.Final.

Conclusion

This is how you override the versions of dependencies used by Spring Boot.

Keep in mind that you should ensure the application stays working since you can’t be sure that those versions are compatible.

Practically speaking, a patch version shouldn’t be breaking, and you can always check the release notes to confirm there are no breaking changes, but just in case.

Leave a comment