2

I have an a project A that has a "managed dependency" a. a is a "shaded jar" (uber-jar) with another dependency b relocated within. The problem is that the version of b relocated into a has several >7.5 CVE's filed against it and I would like to exclude it from the CLASSPATH and use a patched version of b with the CVE's addressed.

How can I do this using Maven3?

EDIT: additional context a is htrace-core4:4.0.1-incubating a transitive dependency of hadoop-common:2.8.3. htrace-core4:4.0.1-incubating is no longer supported and of course contains a vulnerable jackson-databind:2.4.0 shaded jar (b for sake of my labels above) which has proven resilient to normal maven "managed dependency" tactics.

❯ mvn dependency:tree -Dincludes="org.apache.htrace*"          
[INFO] Scanning for projects...
[INFO] 
[INFO] ------------------------< com.s****m.**:s****s >-------------------------
[INFO] Building s*****s 1.21.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-dependency-plugin:3.0.2:tree (default-cli) @ s****s ---
[INFO] com.s****m.**:s****s:jar:1.0.0-SNAPSHOT
[INFO] \- org.apache.hadoop:hadoop-client:jar:2.8.3:compile
[INFO]    \- org.apache.hadoop:hadoop-common:jar:2.8.3:compile
[INFO]       \- org.apache.htrace:htrace-core4:jar:4.0.1-incubating:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.676 s
[INFO] Finished at: 2020-04-27T11:57:11-03:00
[INFO] ------------------------------------------------------------------------
Reuben Peter-Paul
  • 1,550
  • 3
  • 15
  • 25
  • Sorry about the late edit - I slept on the problem (usually a good idea) and did a bit of digging around. Fairly sure including unpack in your build lifecycle to unpack selected parts of uber-jar alongside your compiled code before everything is jarred or warred up should do it. I'll have a go if I get to my laptop later today – Chris Jan 23 '21 at 08:51

1 Answers1

2

There is a question in my mind over whether you should do this if you have any viable alternative.

Sounds like a situation where you are trying to work around something that is just wrong. Conceptually, depending on something that has incorporated specific versions of dependent classes is clearly a potential nightmare especially as you have discovered if there are CVEs identified against one of those shaded dependencies. Depending on an uber-jar essentially breaks the dependency management model.

I'm guessing it is internally created in your organisation, rather than coming from a central repository, so can you put pressure on that team to do the right thing?

Alternatively the dependency plugin's unpack may be an option - unpack that dependency with exclusions based on package into your build - https://maven.apache.org/plugins/maven-dependency-plugin/usage.html#dependency:unpack

The following works for me as an example - unpacks the dependency without the auth package into the classes directory of target before the default-jar is built by maven-jar plugin, and then I have to exclude the original jar - this is a spring-boot project so I use the spring-boot plugin configuration, which is used during the repackage goal, if you are using the war plugin I suspect there is a similar exclusion capability.

End result is the filtered down classes from http client in my jar classes directory alongside my application classes.

            <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <version>3.1.2</version>
            <executions>
                <execution>
                    <id>default-jar</id>
                    <phase>prepare-package</phase>
                    <goals>
                        <goal>unpack</goal>
                    </goals>
                    <configuration>
                        <artifactItems>
                            <artifactItem>
                                <groupId>org.apache.httpcomponents</groupId>
                                <artifactId>httpclient</artifactId>
                                <outputDirectory>${project.build.directory}/classes</outputDirectory>
                                <excludes>org/apache/http/auth/</excludes>
                            </artifactItem>
                        </artifactItems>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>

            <excludes>
                <exclude>
                    <groupId>org.apache.httpcomponents</groupId>
                    <artifactId>httpclient</artifactId>
                </exclude>
            </excludes>
            </configuration>
        </plugin>

Note, since the question update I had a look at htrace-core-4, and you can easily include all the htrace classes without the jackson databind shaded classes using

            <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <version>3.1.2</version>
            <executions>
                <execution>
                    <id>default-jar</id>
                    <phase>prepare-package</phase>
                    <goals>
                        <goal>unpack</goal>
                    </goals>
                    <configuration>
                        <artifactItems>
                            <artifactItem>
                                <groupId>org.apache.htrace</groupId>
                                <artifactId>htrace-core4</artifactId>
                                <outputDirectory>${project.build.directory}/classes</outputDirectory>
                                <excludes>org/apache/htrace/fasterxml/</excludes>
                            </artifactItem>
                        </artifactItems>
                    </configuration>
                </execution>
            </executions>
        </plugin>

then it just remains for you to exclude the original htrace-core4-4.0.1-incubating.jar, which you can do as I have done if you have a spring-boot application, or using the maven war plugin if you are creating a war file or using whatever plugin creates your final build. During unpack you may also want to exclude some of the pom.xml files that are in the jar file and which you don't really need.

Also add a dependency on a safe version of jackson-databind, though there is always the risk that htrace is using a method or class that only exists in the vulnerable version, so you might hit tricky runtime errors.

Chris
  • 1,644
  • 1
  • 11
  • 15
  • I don't see any of @Eugene's comments. – Reuben Peter-Paul Jan 22 '21 at 22:46
  • No, he deleted them, he basically responded straight away that exclusions is the answer, but then in a discussion I think he decided that the point about trying to avoid the need to exclude was more important. I did tell him to add an answer because I think both are equally important - ideally you don't need to do it, and if you have any option to avoid it you should, but if you have to then exclusions based on package should work. – Chris Jan 22 '21 at 22:58
  • @ReubenPeter-Paul Sorry, that is the norm for me. Once something is talked and cleared, I remove the comments, cause its only noise, basically. I agree with this answer ( a lot ), its rather weird to have such exclusions. But at the same time, we have the same thing sometimes, so that link in the answer explains how you could do it with maven. – Eugene Jan 22 '21 at 23:07
  • Eugene and @Chris, I appreciate the answer and discussions. Unfortunately the exclusions didn't seem to work for me. I did apply them to the "parent-bom" where the jar plugin is declared but I will try an override in the actual project pom next. Please see the OP for an update to the context of the problem. – Reuben Peter-Paul Jan 23 '21 at 14:47
  • Have you tried my latest answer example, I had to play around quite a bit but that version is working perfectly for a spring-boot build. The key is making sure the unpack happens before the artifact is built – Chris Jan 23 '21 at 14:53
  • Damn, thinking about it, they haven't just shaded databind in, they've actually repackaged those vulnerable databind classes into org.apache.htrace.fasterxml.databind packages, so the htrace classes will be importing from there and hence bringing in a safe version of fasterxml databind won't help. I believe my answer does what you asked - gives you a way of excluding classes from an uber-jar, but it doesn't help because those classes will have to be there at runtime. I think you need to find an alternative to htrace or a different version. – Chris Jan 24 '21 at 14:08
  • Okay, my last thought on this one, if the specific classes that are the subject of CVEs are not actually used by htrace then you can selectively exclude them, using my answer (unpack exclusions takes a list). – Chris Jan 24 '21 at 14:44