I would like to enforce a strict Maven dependency policy which goes beyond the basic checksumPolicy=fail
approach.
This is an attempt to provide protection against a modified release dependency which still has a valid digest value also known as a "dependency chain attack".
This situation could arise from the following scenarios:
In discussions with other developers one approach to combat the above is to have a list of known MD5/SHA digests in the pom.xml and have Maven verify that the downloaded dependency has the same digest. This ensures that so long as the source code repository remains secure, any included dependencies that have been compromised will be detected.
Thus my question is twofold:
If anyone is wrestling with this issue themselves I've created a Maven Enforcer Plugin Rule that deals with it. You can specify a list of artifact URNs that include the expected SHA1 hash value and have the enforcer verify that this is indeed what is being used in the build.
It is available through Maven Central under MIT license, with source code in GitHub here: https://github.com/gary-rowe/BitcoinjEnforcerRules
While the project indicates that it is for the Bitcoinj library, it is actually a general purpose solution which could be included in any security conscious build process. It will also scan your existing project and identify any problem area while it automatically builds the whitelist for you.
Below is an example of the configuration you'd require in your project to use it.
<build>
<plugins>
...
<!-- Use the Enforcer to verify build integrity -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<id>enforce</id>
<phase>verify</phase>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<digestRule implementation="uk.co.froot.maven.enforcer.DigestRule">
<!-- Create a snapshot to build the list of URNs below -->
<buildSnapshot>true</buildSnapshot>
<!-- List of required hashes -->
<!-- Format is URN of groupId:artifactId:version:type:classifier:scope:hash -->
<!-- classifier is "null" if not present -->
<urns>
<urn>antlr:antlr:2.7.7:jar:null:compile:83cd2cd674a217ade95a4bb83a8a14f351f48bd0</urn>
<urn>dom4j:dom4j:1.6.1:jar:null:compile:5d3ccc056b6f056dbf0dddfdf43894b9065a8f94</urn>
<urn>org.bouncycastle:bcprov-jdk15:1.46:jar:null:compile:d726ceb2dcc711ef066cc639c12d856128ea1ef1</urn>
<urn>org.hibernate.common:hibernate-commons-annotations:4.0.1.Final:jar:null:compile:78bcf608d997d0529be2f4f781fdc89e801c9e88</urn>
<urn>org.hibernate.javax.persistence:hibernate-jpa-2.0-api:1.0.1.Final:jar:null:compile:3306a165afa81938fc3d8a0948e891de9f6b192b</urn>
<urn>org.hibernate:hibernate-core:4.1.8.Final:jar:null:compile:82b420eaf9f34f94ed5295454b068e62a9a58320</urn>
<urn>org.hibernate:hibernate-entitymanager:4.1.8.Final:jar:null:compile:70a29cc959862b975647f9a03145274afb15fc3a</urn>
<urn>org.javassist:javassist:3.15.0-GA:jar:null:compile:79907309ca4bb4e5e51d4086cc4179b2611358d7</urn>
<urn>org.jboss.logging:jboss-logging:3.1.0.GA:jar:null:compile:c71f2856e7b60efe485db39b37a31811e6c84365</urn>
<urn>org.jboss.spec.javax.transaction:jboss-transaction-api_1.1_spec:1.0.0.Final:jar:null:compile:2ab6236535e085d86f37fd97ddfdd35c88c1a419</urn>
<!-- A check for the rules themselves -->
<urn>uk.co.froot.maven.enforcer:digest-enforcer-rules:0.0.1:jar:null:runtime:16a9e04f3fe4bb143c42782d07d5faf65b32106f</urn>
</urns>
</digestRule>
</rules>
</configuration>
</execution>
</executions>
<!-- Ensure we download the enforcer rules -->
<dependencies>
<dependency>
<groupId>uk.co.froot.maven.enforcer</groupId>
<artifactId>digest-enforcer-rules</artifactId>
<version>0.0.1</version>
</dependency>
</dependencies>
</plugin>
...
</plugins>
</build>