Software Supply Chain Security

Maven Dependency Resolution Attacks: Exploiting Java's Build System

Maven's dependency resolution mechanism can be exploited through repository poisoning, dependency confusion, and POM manipulation. Here is what Java teams need to know.

Shadab Khan
DevSecOps Engineer
5 min read

Maven is the dominant build system in the Java ecosystem. It manages dependency resolution for millions of projects, pulling artifacts from Maven Central and other repositories. But Maven's resolution mechanism has characteristics that attackers can exploit, and most Java teams are not aware of the risks.

The core issue is that Maven resolves dependencies through a chain of POM (Project Object Model) files, each of which can declare additional dependencies, repositories, and plugins. This chain of trust extends far beyond what most developers realize, and every link is a potential attack surface.

How Maven Resolves Dependencies

When you declare a dependency in your pom.xml, Maven follows a specific resolution process. First, it checks the local repository (~/.m2/repository). If the artifact is not found locally, Maven queries each configured remote repository in order. The first repository that provides a matching artifact wins.

This resolution order creates several attack opportunities. If an attacker can insert a repository higher in the resolution order, or publish a matching artifact to a repository that Maven checks first, they can substitute malicious code for legitimate dependencies.

Maven also resolves transitive dependencies by reading the POM files of your direct dependencies. Each POM can declare its own dependencies, repositories, and even plugin repositories. A single malicious POM deep in your dependency tree can redirect resolution for entirely unrelated packages.

Attack Vectors

Repository poisoning. If an attacker gains access to a repository that your project trusts, they can replace legitimate artifacts with malicious ones. This is particularly dangerous for internal repositories that may have weaker access controls than Maven Central.

Dependency confusion. Java projects that use internal artifacts with group IDs that are not registered on Maven Central are vulnerable. An attacker can publish an artifact to Maven Central with the same group ID and artifact ID. If Maven checks Central before the internal repository, or if the attacker publishes a higher version number, the malicious artifact may be resolved instead.

POM manipulation. The POM file is XML, and Maven processes it with full XML capabilities. A compromised dependency's POM can declare additional repositories, modify dependency versions through dependency management sections, and introduce plugins that execute during the build.

Plugin repository attacks. Maven plugins execute arbitrary code during the build. A POM that adds a plugin repository can introduce malicious plugins that run with full access to the build environment.

SNAPSHOT version hijacking. SNAPSHOT versions in Maven are mutable -- they can be updated at any time. If your project depends on SNAPSHOT versions from remote repositories, an attacker who compromises the repository can push new SNAPSHOT content at any time.

The Parent POM Problem

Many Java projects use parent POMs for shared configuration. The parent POM is resolved using the same mechanism as any other artifact. If the parent POM is modified, every child project inherits the changes, including dependency version changes, new plugins, and new repository declarations.

This creates a force multiplier for attackers. Compromising a single widely-used parent POM can affect hundreds of downstream projects simultaneously.

The Repository Order Problem

Maven evaluates repositories in the order they are declared. When multiple repositories contain an artifact with the same coordinates, the first match wins. This means that the order of repository declarations in your POM, settings.xml, and any inherited POMs directly affects which artifacts you receive.

Attackers can exploit this by getting a malicious repository inserted before the legitimate one. This can happen through a compromised parent POM, a malicious dependency that adds repositories, or social engineering that convinces a team to add a repository to their configuration.

Practical Defenses

Lock down repository configuration. Use Maven's settings.xml to explicitly define which repositories are trusted. Use the mirrorOf setting to force all resolution through a controlled proxy repository.

Use repository managers. Nexus, Artifactory, or similar tools should proxy all external repositories. Configure Maven to only resolve through your repository manager. This gives you a single point of control and audit for all artifacts.

Enable checksum verification. Maven can verify SHA-1 and MD5 checksums for downloaded artifacts. Set checksumPolicy to fail in your repository configurations to reject artifacts with invalid checksums.

Avoid SNAPSHOT dependencies in releases. Never release software that depends on SNAPSHOT versions. SNAPSHOT artifacts are mutable and can be changed by anyone with write access to the hosting repository.

Sign and verify artifacts. Maven Central requires GPG signing for published artifacts. Configure your build to verify signatures for downloaded artifacts using the maven-gpg-plugin or pgpverify-maven-plugin.

Use the Maven Enforcer Plugin. The enforcer plugin can ban specific dependencies, require dependency convergence, and enforce repository restrictions. It is one of the most effective tools for maintaining dependency hygiene.

Use dependencyManagement. Declare explicit versions for all transitive dependencies in your dependencyManagement section. This prevents transitive POMs from introducing unexpected version changes.

Auditing Your Maven Build

Start by understanding what Maven is actually doing during your build. Run mvn dependency:tree to see the full resolved dependency tree. Run mvn help:effective-pom to see the complete POM after all inheritance and interpolation. Look for repositories, plugins, and dependencies that you did not explicitly declare.

Check your settings.xml for repository configurations that might have been added without review. In corporate environments, the global settings.xml (in the Maven installation directory) and the user settings.xml (in ~/.m2) both affect resolution.

How Safeguard.sh Helps

Safeguard.sh provides deep visibility into your Maven dependency chain, tracking every artifact, repository source, and version resolution. The platform detects dependency confusion attempts, flags artifacts resolved from unexpected repositories, and monitors for changes in transitive dependency trees. With automated SBOM generation and policy enforcement, Safeguard.sh ensures your Java builds resolve only trusted, verified artifacts from approved sources.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.