Maven is the most widely used build system in the Java ecosystem. Its plugin architecture means that virtually every build operation -- compilation, testing, packaging, deployment -- is performed by a plugin. These plugins are downloaded from Maven Central or other repositories and executed with the full privileges of the build process.
Despite this, most Java developers give zero thought to the security of their Maven plugins. They verify runtime dependencies with SCA tools but completely ignore the build-time dependencies that have even more access.
What Maven Plugins Can Access
A Maven plugin executes in the Maven JVM process during the build lifecycle. It has access to:
- The entire project source tree
- All build outputs (compiled classes, packaged artifacts)
- Environment variables, including CI secrets
- The filesystem, with the permissions of the build user
- The network, without restriction
- The Maven settings, including repository credentials
- Other plugin configurations and outputs
A malicious Maven plugin can read your source code, inject bytecode into compiled classes, exfiltrate credentials, or modify your deployment artifacts. And because it runs during the build, the modifications happen before your application-level security checks.
PGP Signature Verification
Maven Central requires PGP signatures for all published artifacts. Every JAR, POM, and plugin on Maven Central has an associated .asc signature file.
However, Maven does not verify these signatures by default. The pgpverify-maven-plugin can verify PGP signatures during the build, but it is not widely adopted. Most builds blindly trust whatever Maven Central serves.
To enable PGP verification, add to your pom.xml:
<plugin>
<groupId>org.simplify4u.plugins</groupId>
<artifactId>pgpverify-maven-plugin</artifactId>
<version>1.18.2</version>
<executions>
<execution>
<goals><goal>check</goal></goals>
</execution>
</executions>
</plugin>
This adds overhead to the build, and you will likely encounter artifacts with missing or untrusted signatures that require configuration exceptions. But for high-security projects, the verification is worthwhile.
Checksum Verification
Maven uses SHA-1 checksums to verify download integrity. When Maven downloads an artifact from a repository, it verifies the checksum matches. This prevents corruption but does not prevent a compromised repository from serving malicious artifacts with matching checksums.
Maven 3.9+ added support for SHA-256 and SHA-512 checksums. Using stronger hashes improves integrity verification but still only protects against transport-level tampering, not repository compromise.
Repository Management
Use a repository manager. Nexus, Artifactory, or similar tools should proxy Maven Central for your organization. This provides:
- Caching (faster builds, protection against upstream outages)
- Scanning (vulnerability and malware detection on incoming artifacts)
- Policy enforcement (blocking specific versions, requiring approvals)
- Audit trails (who downloaded what, when)
Lock down plugin sources. In your Maven settings, configure repositories to only resolve from your managed proxy. Block direct access to Maven Central from CI systems.
Monitor for new plugin versions. When a plugin you use publishes a new version, review it before allowing it into your repository. Automated tools can diff plugin JARs between versions.
Plugin Pinning
Always pin exact plugin versions in your pom.xml. Maven's version resolution for plugins can be unpredictable when ranges are used:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.12.1</version>
</plugin>
Use the maven-enforcer-plugin with requirePluginVersions to ensure all plugins have explicit versions:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.4.1</version>
<executions>
<execution>
<goals><goal>enforce</goal></goals>
<configuration>
<rules>
<requirePluginVersions/>
</rules>
</configuration>
</execution>
</executions>
</plugin>
Build Reproducibility
Maven supports reproducible builds through the project.build.outputTimestamp property. When set, Maven plugins that support reproducibility will produce deterministic output. This allows independent verification that a build has not been tampered with.
<properties>
<project.build.outputTimestamp>2024-01-01T00:00:00Z</project.build.outputTimestamp>
</properties>
Not all plugins support reproducibility. The maven-artifact-plugin can check which plugins in your build are reproducible-compatible.
Plugin Vulnerability Scanning
Standard SCA tools often do not scan Maven build plugins. They focus on <dependencies> in the POM and ignore <plugins>. This creates a blind spot.
To audit plugin dependencies, use mvn dependency:resolve-plugins to list all plugin dependencies, then run vulnerability scanning against this list.
How Safeguard.sh Helps
Safeguard.sh scans both your runtime and build-time Maven dependencies, including plugins and their transitive dependencies. When a vulnerability is found in a Maven plugin in your build configuration, Safeguard.sh alerts you with the same priority as a runtime dependency issue. Our SBOM generation captures the full build-time dependency tree, ensuring complete visibility into your Java build supply chain.