Skip to content

wlami/supply-chain-maven-plugin

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

37 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

supply-chain-maven-plugin

Single-plugin entry point for Maven supply-chain hardening.

Maven Central CI License

What it checks

Check Default Description
minReleaseAge P3D Rejects artifacts published less than N days ago.
requireExactVersions on Rejects version ranges, LATEST, RELEASE.
repositoryAllowlist Central only Effective repositories must be on the allowlist.
baseline auto Enforces .supply-chain-baseline.json if present.
checksumStrict warn Warns when Maven is not in strict checksum mode.
requireReleaseDeps on Rejects SNAPSHOT dependencies.
bannedDependencies empty list User-supplied ban list.
dependencyConvergence on Flags multiple resolved versions of the same GA.
pgpSignature on Verifies .asc signatures against keyserver / pinned map.

Quick start

Add to your pom.xml:

<plugin>
  <groupId>com.wlami</groupId>
  <artifactId>supply-chain-maven-plugin</artifactId>
  <version>0.2.0</version>
  <extensions>true</extensions>
</plugin>

That's it. <extensions>true</extensions> activates a lifecycle participant that auto-binds the check goal to the validate phase. No <executions> block needed. Empty configuration applies the full hardened defaults.

If you'd rather declare the execution explicitly (or want to bind to a different phase), drop <extensions>true</extensions> and add <executions><execution><goals><goal>check</goal></goals></execution></executions> the usual way.

Disabling PGP signature verification

PGP is on by default. Most artifacts on Maven Central ship a .asc, but plenty don't (older releases, internal mirrors, deps from non-Central repos). Two ways to deal:

Disable globally - if signatures aren't available across your dep graph:

<configuration>
  <checks>
    <pgpSignature>false</pgpSignature>
  </checks>
</configuration>

Disable per-artifact (preferred when only a handful lack signatures) - keep PGP on, let the offending artifacts pass:

<configuration>
  <pgpKeysMap>${project.basedir}/pgp-keys-map.list</pgpKeysMap>
</configuration>

pgp-keys-map.list:

# Allow these specific GAVs to pass without a signature.
com.legacy:unsigned-artifact:* = noSig
io.github.example:other-unsigned = noSig

(The noSig token is documented separately; for now the cleanest "I know what I'm doing" path is the global toggle above.)

If you also see timeouts contacting keys.openpgp.org, the verifier emits a per-artifact finding under whatever onNetworkError is set to (default WARN).

Excluding your own artifacts from minReleaseAge

Publishing your own artifact and want to consume it immediately without waiting three days? Add it to the dedicated exclusion list:

<configuration>
  <minReleaseAgeExclusions>
    <exclusion>com.wlami:my-artifact</exclusion>
  </minReleaseAgeExclusions>
</configuration>

Pin to groupId:artifactId. Avoid groupId:* - it matches future artifacts you have not published yet. Combine with <repositoryAllowlist> so the exempted artifact still has to come from a trusted repo.

Goals

  • supply-chain:check - run all enabled checks (bound to validate).
  • supply-chain:report - run checks without failing the build.
  • supply-chain:dump-baseline - write a baseline file of currently resolved deps.
  • supply-chain:refresh-cache - clear the release-date cache.

SARIF output

target/supply-chain.sarif is always produced. Upload to GitHub Code Scanning:

- uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: target/supply-chain.sarif

Design and configuration reference

See docs/superpowers/specs/2026-05-14-supply-chain-maven-plugin-design.md.

Releasing to Maven Central

Releases run on GitHub Actions via .github/workflows/release.yml. The workflow signs with PGP and publishes through the Sonatype Central Portal.

Signing key

Fingerprint 84B3FFEC2085A4CBC92D0DF759E617E4BBD5963D
Email mitzel@tawadi.de
Stored as GitHub Actions secrets MAVEN_GPG_PRIVATE_KEY + MAVEN_GPG_PASSPHRASE
Local backup ~/Library/Application Support/wlami/supply-chain-mvn-plugin-signing.txt (mode 600)
Uploaded to keys.openpgp.org (verify email link to publish UID)

GitHub Actions secrets

Secret Purpose
MAVEN_CENTRAL_USERNAME Sonatype Central Portal user token (username)
MAVEN_CENTRAL_PASSWORD Sonatype Central Portal user token (password)
MAVEN_GPG_PRIVATE_KEY Armored private key for signing
MAVEN_GPG_PASSPHRASE Passphrase for the key

Cutting a release

Two ways:

A. Tag-driven (recommended once autoPublish=true):

mvn versions:set -DnewVersion=0.1.0 -DgenerateBackupPoms=false
git commit -am "release: 0.1.0"
git tag v0.1.0
git push --follow-tags origin main

B. Manual dispatch: trigger Release workflow in the Actions tab; pass version=0.1.0.

After the workflow finishes, the bundle is staged on Central Portal awaiting manual promotion (because autoPublish=false in pom.xml). Promote it in the Central Portal UI. Flip autoPublish to true once you trust the pipeline.

Then bump to the next snapshot:

mvn versions:set -DnewVersion=0.2.0-SNAPSHOT -DgenerateBackupPoms=false
git commit -am "chore: bump to 0.2.0-SNAPSHOT"
git push

Local release (fallback)

MAVEN_GPG_PASSPHRASE=$(cat ~/Library/Application\ Support/wlami/supply-chain-mvn-plugin-signing.txt | awk '/^Passphrase: / {print $2}') \
  mvn -Prelease clean deploy

Requires ~/.m2/settings.xml with the Central Portal token under <server id="central">.

Contributing

All changes land via pull request - main is the release-tracking branch and accepts merges from feature branches only. CI runs on every PR.

License

Apache-2.0.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages