Verification of dependency authenticity in Maven POM based automated build systems

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.

Leave a Comment