Reuben Peter-Paul
Reuben Peter-Paul

Reputation: 1590

How to "exclude" dependencies embedded in an uber-jar using Maven 3?

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

Upvotes: 2

Views: 2447

Answers (1)

Chris
Chris

Reputation: 1804

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.

Upvotes: 2

Related Questions