Maven-Hijack: Software Supply Chain Attack Exploiting Packaging Order

arXiv:2407.18760 · cs.CR, cs.SE · Submitted 2025-10-29 · Read on arXiv

Listen

Radio episode about this paper

Transcript

Introduction to the show: ident: AI Radio. Generated commentary on the latest Artificial Intelligence papers.

Tom: Next we'll be talking about the paper "Maven-Hijack: Software Supply Chain Attack Exploiting Packaging Order".

Jane: The paper was written by Frank Reyes, Federico Bono, Aman Sharma, Benoit Baudry and Martin Monperrus from KTH Royal Institute of Technology and Université de Montréal.

Tom: Stay tuned as we take you through the paper and discuss its implications.

Jane: We also have Lu with us today — senior AI researcher at Tsinghua.

Tom: We also have Meng with us today — lead engineer at a mysterious AI startup.

Jane: We also have Lalam with us today — the in-house Large Language Model.

Tom: Alright, let's get started.

Title: Tom: Welcome back, everyone. Today we're looking at a paper that's going to make you think twice about how you build Java projects. It's called "Maven-Hijack: Software Supply Chain Attack Exploiting Packaging Order."

Jane: And Tom, I have to say, the title alone got my attention. "Packaging order" sounds so mundane, but this paper shows it's actually a security vulnerability.

Tom: Exactly. Jane, when you think about supply chain attacks, you usually think about someone sneaking malicious code into a library, right? This is different. The authors — Frank Reyes, Federico Bono, Aman Sharma, Benoit Baudry, and Martin Monperrus — they found a way to hijack an application without ever touching the code you actually wrote.

Jane: So walk me through this. If I'm a developer and I use Maven to manage my dependencies, what's happening that I don't know about?

Tom: So when Maven packages your project, it goes through your dependency tree in a specific order — depth-first search. It's like walking through a family tree, going all the way down one branch before moving to the next. And that order determines what ends up first in your final JAR file.

Jane: And that matters because...?

Tom: Because of how Java loads classes at runtime. The Java Virtual Machine scans the classpath in order and loads the first class it finds with a matching name. So if an attacker can get a malicious class placed earlier in that packaging order, it shadows the legitimate one.

Jane: Oh, that's sneaky. So it's not about renaming anything or overriding versions. It's literally about who gets to the finish line first.

Tom: Right. And the paper calls these two pieces the "gadget dependency" — which has the legitimate class you want to hijack — and the "infection dependency" — which is where the attacker plants the malicious class. The infection just needs to appear earlier in the dependency tree.

Jane: So the attacker needs to compromise some dependency that the project uses, but it doesn't have to be a direct dependency. It could be buried deep in the tree.

Tom: Exactly. And that's what makes it so dangerous. The paper demonstrates this on the Corona-Warn-App, Germany's COVID contact tracing app. They injected a malicious class into a transitive dependency called everit-json-schema, and that let them hijack the PostgreSQL database driver.

Jane: The database driver. That's the thing that handles all the credentials and queries. That's a big deal.

Tom: It's a huge deal. They got full control over the database connection logic without modifying a single line of the application's own code. The app just builds and runs like normal, but the attacker is silently stealing credentials and intercepting queries.

Jane: Tom, this feels like one of those attacks that's so elegant it's almost scary. It's not brute force. It's exploiting the way the system is designed to work.

Tom: And that's why we're covering it. Let's bring in Lu and Meng to get their take on this.

Lu: I love this paper because it reframes the problem. We usually think about "what code is running" but not "where did that code come from in the classpath." The authors show that the order of resolution is itself an attack surface.

Meng: From an engineering standpoint, what worries me is that this is silent. The build succeeds. The tests might even pass. And you've got no idea that the class being loaded isn't the one you think it is.

Jane: So the title "Maven-Hijack" really captures it — the build tool itself is being used against you. And the fact that they demonstrated it on a real, widely-used app makes it concrete.

Tom: Next, we're going to dig into the actual attack steps and how they pulled this off in practice. Stay with us.

Summary: Jane: So we're back with "Maven-Hijack: Software Supply Chain Attack Exploiting Packaging Order." Tom, last time we talked about the big picture. Now let's get into the actual mechanics of how this attack works.

Tom: Right. The paper breaks it into three steps. First, the attacker identifies a target application that has both a gadget dependency and an infection dependency in its tree. The gadget has the class you want to shadow. The infection is the weak link — maybe it's unmaintained, or the attacker can compromise the maintainer's account.

Jane: So it's a two-part requirement. You need a valuable target class and a vulnerable entry point that happens to be packaged earlier.

Tom: Exactly. And in their proof of concept, the gadget is the PostgreSQL JDBC driver. That's a great target because database connections happen at startup, so you know your malicious code will run.

Lu: And the infection dependency is everit-json-schema, which is a transitive dependency of the Corona-Warn-App backend. It appears earlier in the dependency tree than the PostgreSQL driver. That ordering is the whole attack.

Tom: Step two is order tampering. The attacker publishes a compromised version of the infection dependency. They don't change any existing classes in it. They just add a new dependency that contains a malicious class with the same fully qualified name as the legitimate one — in this case, org.postgresql.Driver.

Jane: So they're not modifying the library. They're adding a Trojan horse inside it.

Tom: Right. And step three is the hijacking at runtime. When the app starts, Spring Boot tries to establish a database connection. The classloader scans the classpath in order, finds the malicious Driver class first, and loads it instead of the real one.

Meng: What I find striking is that the classloader has no idea anything is wrong. It's doing exactly what it's supposed to do — load the first match. The problem is that the packaging order put the wrong class first.

Jane: And the paper says the malicious class can do things like read credentials, intercept queries, or leak confidential data. All transparently. The application runs normally, from the user's perspective.

Tom: And here's the thing — the paper also tested this across different Maven packaging plugins. Most of them are vulnerable. The standard maven-jar-plugin and spring-boot-maven-plugin both let the attack succeed. The maven-shade-plugin emits a warning but still packages the malicious version.

Lu: The maven-assembly-plugin is interesting because it uses a hash set, so the order isn't guaranteed. The attack only works sometimes. But that's not a defense, that's just randomness.

Meng: So the attack works on the most common build setups. That's not a niche vulnerability. That's the default configuration for a huge number of Java projects.

Jane: And the paper also looks at Gradle. It's harder there because Gradle uses breadth-first search for the classpath, so direct dependencies come first. And Gradle doesn't automatically pull from custom repositories the way Maven does. But the attack is still possible, just more constrained.

Tom: So the summary is: this attack is real, it's practical, and it works on real-world applications. The question becomes — what do we do about it? That's what we're going to talk about next.

Improvements: Tom: We're back with "Maven-Hijack: Software Supply Chain Attack Exploiting Packaging Order." Jane, we've established that the attack works. Now let's talk about the defenses the paper evaluates.

Jane: And there are three of them, right? Sealed JARs, Java Modules, and the Maven Enforcer plugin.

Tom: Right. Sealed JARs are the first line of defense. The idea is that a JAR can declare that all classes in a particular package must come from that same archive. So if the PostgreSQL driver is in a sealed JAR, the JVM will throw a SecurityException when it tries to load the malicious class from a different JAR.

Meng: But the paper points out that this can be bypassed. An attacker can just copy the entire package into the infection dependency. Then the JVM loads everything from there and never even looks at the sealed JAR.

Jane: So sealed JARs are a speed bump, not a wall.

Tom: Exactly. Then there are Java Modules, which came with Java nine. If you modularize your application and all your dependencies, the module system detects package conflicts at compile time. It literally fails the build with an error saying the module reads the same package from two different modules.

Lu: That's strong protection. But the paper cites research showing that only about one point six nine percent of artifacts on Maven Central actually include a module-info.java file. Adoption is incredibly low. So in practice, almost nothing is protected.

Meng: And modularizing a large existing project is a huge undertaking. It's not something you can just flip on.

Tom: Which brings us to the third option — the Maven Enforcer plugin with the banDuplicateClasses rule. This is the one the paper recommends as the most practical defense.

Jane: How does that work?

Tom: You add a small configuration to your pom.xml. During the build, Maven scans all the dependencies for classes with the same fully qualified name. If it finds a conflict — like org.postgresql.Driver appearing in two different JARs — it fails the build and lists the conflicting classes.

Meng: So it catches the problem at build time, before anything ships. That's much better than discovering it at runtime.

Jane: But the paper also mentions that this rule might flag legitimate duplicates, right? Like when libraries split packages across multiple artifacts.

Tom: Right. There can be false positives. But the paper argues that the security benefit outweighs that cost. And the plugin is independent of how dependencies are packaged, so it works across different Maven setups.

Lu: What I find interesting is that none of these defenses are on by default. The Enforcer plugin has to be explicitly configured. Sealed JARs have to be declared by the library maintainer. Java Modules have to be adopted by the whole ecosystem. So the attack surface remains wide open for most projects.

Jane: So the improvement here isn't just a technical fix. It's also a call to action for the community to adopt these safeguards.

Tom: And that's the takeaway — the tools exist, but they're not being used. Next, we'll wrap up with our final thoughts on what this means for the future of software supply chain security.

Conclusion: Jane: We're wrapping up our discussion of "Maven-Hijack: Software Supply Chain Attack Exploiting Packaging Order." Tom, this has been a fascinating conversation.

Tom: It really has. Let's recap what we've learned. The paper defines a new class of supply chain attack that exploits the order in which Maven packages dependencies and the way the Java classloader resolves classes at runtime. No renaming, no version overrides — just careful placement of a malicious class earlier in the packaging order.

Jane: And they proved it works on a real-world application, the Corona-Warn-App, by hijacking the PostgreSQL database driver through a transitive dependency.

Meng: The most practical defense is the Maven Enforcer plugin with banDuplicateClasses. It catches conflicts at build time and is easy to enable. The other options — sealed JARs and Java Modules — have real limitations or adoption problems.

Lu: And the deeper lesson is that build tools and runtime environments have assumptions baked into them that we don't question. The classloader assumes the first match is the right match. Maven assumes the packaging order is irrelevant. This paper shows those assumptions are attack vectors.

Jane: And that's why this research matters. It's not just about one vulnerability. It's about understanding how the design of our tools creates blind spots that attackers can exploit.

Tom: The authors also extended the analysis to Gradle, showing the attack is harder but still possible there. And they've made their proof of concept publicly available, which is great for researchers and security folks who want to study it further.

Jane: So what's the big picture? Software supply chain security needs to be proactive, not reactive. We can't just wait for the next attack to be discovered. We need to build defenses into the default configuration of our tools.

Tom: Well said, Jane. And with that, we're going to say goodbye to "Maven-Hijack" and get ready for our next paper. Thanks to Lu and Meng for joining us today.

Lu: Thanks for having me. This was a great one.

Meng: Agreed. See you next time.

Jane: And thank you, listeners, for tuning in. Until next time, keep questioning how your software is built.

Tom: See you all on the next episode.

Frank Reyes, Federico Bono, Aman Sharma, Benoit Baudry, Martin Monperrus

KTH Royal Institute of Technology · Université de Montréal

cs.CR, cs.SE

Submitted: 2025-10-29

Journal ref: Proceedings of ACM Workshop on Software Supply Chain Offensive Research and Ecosystem Defenses (SCORED), 2025

DOI: 10.1145/3733827.3765523

Code: https://github.com/chains-project/maven-class-hijack-poc

License: http://arxiv.org/licenses/nonexclusive-distrib/1.0/

Importance score: 61/100

The gist: The paper introduces Maven-Hijack, a novel class of software supply chain attack that exploits the order in which Maven packages dependencies and the way the Java Virtual Machine resolves classes at

Key concepts

Packaging Order
When Maven packages a project, it traverses the dependency tree using a depth-first search. This specific order dictates what ends up first in the final JAR file. This sequence is crucial because it determines which class gets loaded first by the Java Virtual Machine at runtime.
Gadget Dependency
This is the target component containing the legitimate class that developers want to hijack. In a successful attack, this component holds the valuable code that an attacker wishes to shadow or replace with malicious functionality.
Infection Dependency
This is where the attacker plants their malicious class. The infection only needs to appear earlier in the dependency tree than the legitimate target class, allowing it to take precedence during runtime loading.
Runtime Hijacking
The Java Virtual Machine scans the classpath in order and loads the first matching class it finds. By placing a malicious class earlier in the packaging order, an attacker can cause this mechanism to load their code instead of the intended legitimate code.

Terminology

Summary

The paper introduces Maven-Hijack, a novel class of software supply chain attack that exploits the order in which Maven packages dependencies and the way the Java Virtual Machine resolves classes at runtime. The attack works by injecting a malicious class with the same fully qualified name as a legitimate one into a dependency that is packaged earlier, allowing an attacker to silently override core application behavior without modifying the main codebase or library names.

The attack is a three-step process:

1. Attack Preparation: The attacker identifies a target application with two weaknesses in its dependency tree: a gadget dependency and an infection dependency. A gadget dependency is a dependency, which identifiers can be reused to compromise the classpath of an application. An infection dependency is a weak link in the dependency tree of the target application where the attacker can inject a malicious class, such as a dependency that is unmaintained or has few commits. The attacker must be able to modify the Pom file of a project through means such as gain publishing rights over the infection dependency, compromise publishing credentials, or reclaim abandoned projects.

2. Order Tampering: The attacker injects a malicious class into the infection dependency with the same fully qualified name as a legitimate class in the gadget dependency. The malicious class is bundled with the infection dependency and uploaded to a public repository such as Maven Central. When the target application is next built, the malicious class is included in the artifact according to the packaging order.

3. Hijacking Execution at Runtime: When the victim's application executes, the Java classloader searches for the legitimate class in the classpath sequentially. Since the infection dependency is included before the gadget dependency in the packaging order, the classloader finds the malicious class first and loads it instead of the legitimate one.

The attack exploits two key design decisions:

Packaging in Maven: Maven packages project artifacts by traversing the dependency tree in Depth First Search (DFS) order. The first node is the classes of the project itself, followed by dependency classes. For example, the DFS order of a sample dependency tree is: Project, D1, D11, D111, D112, D2, D21, D211, D22, D221.

Class loading in Java: Java employs a linear search mechanism over the classpath, checking each entry one by one until it finds the class whose fully qualified name matches the one invoked. This allows an attacker to hijack a class by placing a malicious class with the same name earlier in the classpath.

The researchers implemented the attack on the Corona-Warn-App, Germany's coronavirus tracking application used during the 2020 pandemic. The backend services are written using Spring Boot. They identified:

  • Infection dependency: everit-json-schema, which appears in the dependency tree before the gadget dependency

  • Gadget dependency: the PostgreSQL JDBC driver (org.postgresql:postgresql)

The attack targets the org.postgresql.Driver class. Since database connections are initialized at startup, the payload is guaranteed to execute. The compromised version of everit-json-schema adds a malicious dependency containing a malicious implementation of org.postgresql.Driver. When the backend service starts, Spring Boot attempts to establish a database connection, and the classloader loads the malicious driver instead of the legitimate one. The malicious class can silently exfiltrate sensitive information from the client during runtime, including reading credentials, intercepting queries, or leaking confidential data.

The paper evaluates three mitigation strategies:

1. Sealed JARs: A sealed JAR enforces that all classes belonging to a specific Java package must be loaded from the same archive. If the gadget dependency is published as a sealed JAR, the malicious class in the infection dependency violates this restriction, and a SecurityException is thrown at runtime. However, this defense can be bypassed if the attacker includes a fully self-contained copy of the original package in the infection dependency, since the JVM will load all classes from the infection dependency and not search the gadget dependency.

2. Java Modules: With Java 9's Project Jigsaw, modularized applications are immune to Maven-Hijack because a package collision results in an automatic compilation failure. Two approaches exist: (1) defining the target application as a module and importing all direct and transitive dependencies as modules, or (2) defining modules for each dependency and the target application. However, Java modules are not widely adopted—only 1.69% of over 473,000 artifacts in Maven Central include a module-info.java file.

3. Maven Enforcer Plugin: The maven-enforcer-plugin with the banDuplicateClasses option fails the build process if a class collision is detected. This provides the most practical defense, as it works at build time, is independent of how dependencies are packaged, and only requires the developer to enable the plugin. However, it may flag legitimate duplicate classes when libraries split packages across multiple artifacts.

The paper evaluates attack feasibility across different Maven packaging plugins:

  • maven-jar-plugin: attack successful

  • spring-boot-maven-plugin: attack successful

  • maven-shade-plugin: attack successful (emits warnings but build continues)

  • quarkus-maven-plugin: attack successful (emits warnings)

  • maven-bundle-plugin: attack successful (requires reversed dependency order)

  • maven-assembly-plugin: attack sometimes successful (order not guaranteed due to hash table-based set)

The paper extends analysis to Gradle, finding the attack is feasible but significantly more challenging. Gradle uses breadth-first search for classpath generation, meaning direct dependencies are included first, reducing the attack surface. Additionally, Gradle ignores custom repositories for transitive dependencies, requiring manual declaration of repositories in the build script.

The paper distinguishes Maven-Hijack from prior attacks:

  • Dependency confusion and typosquatting exploit naming ambiguities, whereas Maven-Hijack relies solely on dependency ordering

  • MavenGate exploited ownership assumptions in Maven's groupId namespace by re-registering expired domains

  • Prior work on dependency conflicts (Wang et al.) focused on semantic changes from version conflicts, not adversarial manipulation

The paper concludes that critical vulnerabilities in the Maven and Java ecosystems enable the attack, specifically the lack of control between the artifact metadata and the actual package content, combined with the class loader's behavior of loading the first matching class in the classpath without collision checks. The Maven Enforcer Plugin provides effective mitigation but is not enforced by default, highlighting the need for enforced safeguards in dependency management.

Improvements for AI systems

Based on the paper, here are specific improvements that can be made to AI systems, particularly those involved in code generation, dependency management, and software supply chain security:

1. AI-Powered Dependency Auditing Agent

  • Improvement: Train a model to statically analyze a project's pom.xml (or build.gradle) and its resolved dependency tree to detect Maven-Hijack conditions before build time. The model should specifically check for: (a) the presence of a gadget dependency (e.g., org.postgresql:postgresql) and (b) an infection dependency that appears earlier in the DFS packaging order and is unmaintained or has low commit activity.

  • Capability: The AI system can automatically flag a build as high-risk and suggest reordering dependencies or adding the maven-enforcer-plugin with banDuplicateClasses to the build configuration. It can also generate a report listing all classes that are at risk of being shadowed, along with the exact packaging order.

2. Classpath Collision Prediction for Code Generators

  • Improvement: Enhance LLM-based code generators (e.g., Copilot, Codex) to include a post-generation validation step. After generating code that imports external libraries, the AI should simulate the JVM classloader's linear search. It can predict whether a generated class name (e.g., a custom org.postgresql.Driver) would collide with a class from a transitive dependency that appears earlier in the classpath.

  • Capability: The improved system can refuse to generate code that would introduce a class shadowing vulnerability, or it can automatically refactor the generated code to use a different package name or a unique class name, preventing the attack vector at the source.

3. Automated Mitigation Advisor for CI/CD Pipelines

  • Improvement: Build an AI agent that integrates with CI/CD systems (e.g., Jenkins, GitHub Actions). When a build succeeds but contains duplicate classes (as detected by maven-shade-plugin warnings), the agent can automatically evaluate the severity. It can distinguish between benign duplicates (e.g., split packages) and malicious ones (e.g., a class from an unmaintained library shadowing a core JDBC driver).

  • Capability: The agent can autonomously patch the build configuration by adding the maven-enforcer-plugin rule, or it can block the deployment and alert the security team with a specific explanation of which dependency is the infection and which is the gadget, along with the exact class names involved.

4. Semantic-Aware Dependency Graph Analyzer

  • Improvement: Train a graph neural network (GNN) on Maven Central metadata and historical vulnerability data. The model should learn to identify gadget dependencies (those with high-value classes like database drivers, authentication libraries, or crypto providers) and infection dependencies (those with low maintenance, few contributors, but high transitive usage). The model can then rank the risk of a given dependency tree.

  • Capability: The AI system can proactively recommend that developers seal their JARs or migrate to Java Modules for high-risk combinations. It can also generate a risk score for each dependency update, warning if a new version of a transitive dependency introduces a class that shadows a critical class from a direct dependency.

5. Runtime Anomaly Detection for Class Loading

  • Improvement: Create an AI-based runtime monitor that hooks into the JVM's class loading events (via JVMTI). The model learns the normal mapping of fully qualified class names to their source JARs. If a class is loaded from an unexpected JAR (e.g., org.postgresql.Driver loaded from everit-json-schema instead of postgresql), the AI flags it as an anomaly.

  • Capability: The system can automatically terminate the application or trigger an alert, preventing data exfiltration. It can also generate a detailed trace showing the classpath order and the exact injection point, helping developers identify the compromised dependency.

6. Gradle-Specific Attack Surface Reducer

  • Improvement: For AI tools that generate Gradle build scripts, incorporate the paper's findings on BFS ordering. The AI can automatically reorder dependencies in the dependencies block to ensure that gadget dependencies are declared before potential infection dependencies, or it can enforce the use of implementation over api to limit transitive exposure.

  • Capability: The improved AI can generate build scripts that are inherently more resistant to class hijacking, even without additional plugins, by leveraging the BFS ordering to place trusted, high-value libraries earlier in the classpath.

Sources

Related papers