Using Maven to Generate a Dependency Tree in Java: A Step-by-Step Guide

2022/01/11

Tags: tech ops security SBOM flux java supply chain

Since Log4j is the topic of the day, let’s pick a Java project using a vulnerable version and generate a dependency manifest to check for Log4j. Using Google’s Open Source Insights tool, search for a vulnerable version of Log4j and then select a dependent project. We will be using Java and Maven for this tutorial.

In this example, start by searching for the vulnerable log4j-api package (hint: You can check the example service advisory on OSI’s front page right now to get the package name).

Using the version selection dropdown next to the package name, select an older, vulnerable version of log4j

Now look for dependent packages

Nacos-client looks like a good subject for this example, so let’s grab that project off of Github by following the Github link on the right side and cloning it as you would any other project.

After cloning the repo, follow the included instructions for building the main project. In this case, you will need these artifacts in place in order to work with some of the sub-projects such as nacos/client.

➜ ~ git:(main) ✗ cd $(mktemp -d)
➜  tmp.ihqwuqkwSV git clone git@github.com:alibaba/nacos.git
➜  tmp.ihqwuqkwSV  cd nacos && pwd
/tmp/tmp.ihqwuqkwSV/nacos
➜  nacos  git:(develop) mvn -Prelease-nacos -Dmaven.test.skip=true clean install -U

After a whole lot of text on your screen, a successful build should look like this:

[INFO] Reactor Summary for Alibaba NACOS 2.1.0-SNAPSHOT 2.1.0-SNAPSHOT:
[INFO]
[INFO] Alibaba NACOS 2.1.0-SNAPSHOT ....................... SUCCESS [ 18.555 s]
[INFO] nacos-api 2.1.0-SNAPSHOT ........................... SUCCESS [  8.023 s]
[INFO] nacos-common 2.1.0-SNAPSHOT ........................ SUCCESS [  4.196 s]
[INFO] nacos-consistency 2.1.0-SNAPSHOT ................... SUCCESS [  4.532 s]
[INFO] nacos-sys 2.1.0-SNAPSHOT ........................... SUCCESS [  2.699 s]
[INFO] nacos-auth 2.1.0-SNAPSHOT .......................... SUCCESS [  0.827 s]
[INFO] nacos-core 2.1.0-SNAPSHOT .......................... SUCCESS [  7.411 s]
[INFO] nacos-config 2.1.0-SNAPSHOT ........................ SUCCESS [ 10.027 s]
[INFO] nacos-cmdb 2.1.0-SNAPSHOT .......................... SUCCESS [  0.432 s]
[INFO] nacos-naming 2.1.0-SNAPSHOT ........................ SUCCESS [  9.030 s]
[INFO] nacos-address 2.1.0-SNAPSHOT ....................... SUCCESS [  0.484 s]
[INFO] nacos-client 2.1.0-SNAPSHOT ........................ SUCCESS [ 15.278 s]
[INFO] nacos-istio 2.1.0-SNAPSHOT ......................... SUCCESS [  6.335 s]
[INFO] nacos-console 2.1.0-SNAPSHOT ....................... SUCCESS [  5.891 s]
[INFO] nacos-test 2.1.0-SNAPSHOT .......................... SUCCESS [  1.070 s]
[INFO] nacos-config-test 2.1.0-SNAPSHOT ................... SUCCESS [  0.140 s]
[INFO] nacos-naming-test 2.1.0-SNAPSHOT ................... SUCCESS [  0.152 s]
[INFO] nacos-core-test 2.1.0-SNAPSHOT ..................... SUCCESS [  0.144 s]
[INFO] nacos-example 2.1.0-SNAPSHOT ....................... SUCCESS [  0.252 s]
[INFO] nacos-distribution 2.1.0-SNAPSHOT .................. SUCCESS [  8.997 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  01:46 min
[INFO] Finished at: 2022-01-06T19:20:56-05:00
[INFO] ------------------------------------------------------------------------

Now navigate into the nacos/client directory and confirm you see a pom.xml file.

➜  nacos  git:(develop) cd ./client
➜  client  git:(develop) ls -lah
total 52K
drwxrwx---  4 fraq fraq 4.0K Jan  6 19:20 .
drwxrwx--- 25 fraq fraq 4.0K Jan  6 19:19 ..
-rw-rw----  1 fraq fraq  16K Jan  6 19:20 .flattened-pom.xml
-rw-rw----  1 fraq fraq  18K Jan  6 19:03 pom.xml
drwxrwx---  4 fraq fraq 4.0K Jan  6 19:03 src
drwxrwx---  6 fraq fraq 4.0K Jan  6 19:20 target

Now, finally, we can generate a list of dependencies as a tree and (optionally) search for log4j in the list.

➜  client  git:(develop) mvn dependency:tree | grep log4j
[INFO] +- org.apache.logging.log4j:log4j-core:jar:2.17.0:compile
[INFO] +- org.apache.logging.log4j:log4j-api:jar:2.17.0:compile
[INFO] +- org.apache.logging.log4j:log4j-slf4j-impl:jar:2.17.0:compile

And there you have it: a way to enumerate and search dependencies (and see what declares what) in your Maven projects. Similar tooling exists for many other languages, but the actual process is unique for all of them, unfortunately. Automating this? That’s an entirely different story and an area that’s ripe for improvement.

Like this post? Got questions? Tweet me!