I was just pointed to a very interesting article about a security problem called
Cross Build Injection (XBI). Bascially it is a fancy name for smuggling bad code
into an application at build time via automated build systems such as ant, maven or ivy.
The problem could be alleviated by introducing a cryptographic signature validation für dependencies as it is currently in place with many operating systems for downloading packages.
To be clear: I am not talking about simply providing md5 or sha1 hashes for the artifacts. That is already done, but those hashes are stored in the same location as the artifacts. So once a malicious hacker compromises the repository and can replace the artifact they can replace the hashes as well.
So what is acutally needed is some kind of PKI, that allows the developers to sign their artifacts and maven to verify these signatures. Since the signature is done using the private key of the developer it cannot be tampered with when only the repository is compromised.
Does anyone know the state of this in maven?
Update: The checksums mentioned below are indeed only for integrity checks and are indeed stored with the artifacts so they don't answer the question.
Actually, one need to sign artifacts using PGP to upload them to a repository that is synced with central (the Maven GPG Plugin can help for this step). To verify signatures at download time, you are invited to use a repository manager supporting this feature. From How to Generate PGP Signatures with Maven:
If you use a tool that downloads
artifacts from the Central Maven
repository, you need to make sure that
you are making an effort to validate
that these artifacts have a valid PGP
signature that can be verified against
a public key server. If you don’t
validate signatures, then you have no
guarantee that what you are
downloading is the original artifact.
One way to to verify signatures on
artifacts is to use a repository
manager like Nexus Professional. In
Nexus Professional you can configure
the procurement suite to check every
downloaded artifact for a valid PGP
signature and validate the signature
against a public keyserver.
If you are developing software using
Maven, you should generate a PGP
signature for your releases.
Releasing software with valid
signatures means that your customers
can verify that a software artifact
was generated by the original author
and that it hasn’t been modified by
anyone in transit. Most large OSS
forges like the Apache Software
Foundation require all projects to be
released by a release manager whose
key has been signed by other members
of the organization, and if you want
to synchronize your software artifacts
to Maven central you are required to
provide pgp signatures.
See also
- How to Generate PGP Signatures with Maven
- Uploading Artifacts to the Central Maven Repository: DIY
The Maven Install Plugin can be configured to create integrity checksums (MD5, SHA-1) and you can configure a checksum policy per repository (see checksumPolicy
).
Maven repository managers can/should also be able to deal with them. See for example:
- 6.5. Managing Repositories
tl;dr:
Non-existent verification mechanisms in Maven and missing language constructs in the POM's DSL are a serious security threat. Until MNG-6026 is addressed, use someting like Gradle Witness.
Introduction
None of the answers provided so far seem to solve the problem. Signing artifacts is only a first step into the right direction. But the condition when a key used to sign the artifact is considered to be trusted/valid is very opaque. For example: How does pgpverify-maven-plugin or Nexus Professional actually verify that the signature is valid for the artifact? Just retrieving the key from keyserver and verifying the artifact is no enough.
Sonatype mentions this briefly in their blog post:
PGP Signatures: Another Level
On the consumption side, you can use Procurement in Nexus Professional
to check for the presence of a signature, and on the publishing side
signing your releases with a PGP signature and making PGP signatures
available on a public keyserver will help people double-check that
artifacts and checksums are consistent. Note: I think there’s more
work to be done to create tools that encourage the use of PGP keys
and, more importantly, give repository administrators some control
over what keys are to be trusted.
(emphasis mine)
Extending the Project Object Model (POM) with trust information
What we need is the possibility to model a trust relation from your project or artifact to the declared dependencies. So that, if all involved parties declare such a relation, we are able to create a "chain of trust" from the root (e.g. the project) over its dependencies down to the very last transitive dependency. The Project Object Model (POM) needs to be extended by a <verification/> element for dependencies.
Current Situation
Right now we have something like
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.0</version>
</dependency>
Hard dependencies
For hard dependencies, <verfication/> could include the sha256sum of artifact and its POM file:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.0</version>
<verification>
<checksum hash='sha-256'>
<pom>[sha256 of junit pom file]</pom>
<artifact>[sha256sum of artifact (junit.jar)]</artifact>
</checksum>
</verification>
</dependency>
Soft dependencies
If soft or ranged dependencies are used, then we could specify the public key (or multiple) of the keypair used to sign the artifacts
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>[4.0,4.5)</version>
<verification>
<openpgp>[secure fingerprint of OpenPGP key]</openpgp>
<!-- possible further 'openpgp' elements in case the artifacts in the
specified version range where signed by multiple keys -->
</verification>
</dependency>
And now?
Thanks to peter triggering me, I've raised a feature request for Apache Maven: MNG-6026. Let's see what happens next.
Other approaches
Gradle Witness does something similar for gradle. But it has some disadvantages:
- It is built on top of gradle (and built in POM)
- It does only allow hard dependencies, because it uses hashes.
The same seems to be true for the Maven Enforcer Plugin.
pgpverify-maven-plugin appearently also follows this approach. Although documentation is missing there is a test for a so called keysMap
property, which also appears in the config file as keysMapLocation
.
"The problem could be alleviated by introducing a cryptographic signature validation für dependencies as it is currently in place with many operating systems for downloading packages."
What you are looking for signing your jar files.
http://download-llnw.oracle.com/javase/1.3/docs/tooldocs/win32/jarsigner.html
You need to protect your private key with appropriate measures. But if you are paranoid about such a composure you may need to look about PKI , Public Key Infrastructures.
It is now possible to validate PGP signatures in maven by using this plugin: http://www.simplify4u.org/pgpverify-maven-plugin/index.html
Here's how to configure it in your parent pom.xml
:
<build>
<plugins>
<plugin>
<groupId>com.github.s4u.plugins</groupId>
<artifactId>pgpverify-maven-plugin</artifactId>
<version>1.0.0</version>
<configuration>
<pgpKeyServer>https://pgp.mit.edu</pgpKeyServer>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
<phase>install</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
This configuration binds the PGP check to the install
phase.
If you don't want to run the check all the time, remove the <executions />
element and run it manually like so:
mvn com.github.s4u.plugins:pgpverify-maven-plugin:check