The state of package signing across package managers

Tieg Zaharia
by Tieg Zaharia
on June 11, 2020

Recently I looked at the state of 2FA support across package managers. 2FA adds a layer of security by requiring two sources of authentication from maintainers when publishing packages. This helps open source communities avoid supply-chain attacks by protecting packages from their author to their repository. 

pkg-signing-pic-1

2FA is great, but hinges upon the package repository being secure, and isn’t an end-to-end verification that a package came from its maintainer. 

But there’s another way that isn’t as dependent upon the package repository: cryptographic signing of packages. Let’s take a look at which platforms support package signing.

But first, what is package signing?

Package signing is the act of an open source package (repo, binary, recipe, etc.) being cryptographically signed with a private key so that downstream users can verify the package with a public key.

Across language ecosystems, there are generally two types of package signing:

  1. Signed-by-repository: the repository signs uploaded packages, and users verify them after downloading. 
    package-signing-ic-2
  2. Signed-by-author: the author signs packages before uploading them to a repository, and users verify them after downloading from the repository. This is an end-to-end guard to ensure the package was uploaded by its maintainers.
    pck-signing-pic-3

Why is package signing useful?

Whether you’re setting up a new codebase on your developer machine or deploying a webapp to your servers, you’re probably downloading dozens—or hundreds—of open source packages. It’s impractical to comb through every line of code to make sure the package you received was not tampered with. Package signing offers a way to say I trust this maintainer and I am guaranteed that this code was uploaded by them.

Which programming language package managers support package signing?

Let’s try to classify what each package manager does currently:

Author-signing:

Repository-signing:

  • npm: npm signs packages with its own PGP key, which is publicized on Keybase.
    • Caveat: although npm doesn’t have native author-signing, there is some 3rd-party tooling available via the pkgsign library.
    • More: some interesting discussions about signing have happened on node-forward, and npm.

In progress:

  • Pypi: Python 2.5 added support for author-signing with GPG (via python setup.py --sign upload), but there is no built-in support to verify those signatures yet.
  • Wordpress: discussion of signing happened here, and signing of Wordpress itself was added here. As of 5.2, WordPress updates are now signed, but plugins and themes are still unsigned.
    • Caveat: there’s an open discussion about implementing author-signing via a PKI called Gossamer.

Partial or no signing:

  • Go Modules (Go): as of Go 1.13, Go Modules verifies downloaded packages (which are usually git repos) against a checksum database.
  • Composer (PHP): there have been discussions of built in signing/verification here.
  • Cargo (Rust): crates are hosted on GitHub*, and the Rust community has discussed package signing here, here and here.
  • CPAN (Perl): no built-in support, but author-signing is available via 3rd party package manager pp (or the underlying cpansign cli)
  • Carthage (Cocoa): packages are hosted on GitHub*, GitLab**, Bitbucket***, etc
  • Julia Pkg (Julia): packages are hosted on GitHub*, GitLab**, Bitbucket***, and registered with the Julia Package Registry on github.
  • Bower (JS): packages are hosted on GitHub*, GitLab**, Bitbucket***, etc
  • PDK (Puppet)
  • Meteor (Meteor)
  • Cabal (Haskell)
  • Mix (Erlang)
  • R (R)

Does package signing matter?

If you read through the discussions linked to above, package signing is indeed a lofty goal and challenging to get right. So is it worth it, and could it prevent any classes of exploits? You can find some examples of supply chain attacks from the past decade documented here and here. Those lists contain some examples of repository account takeovers and other exploits that could be mitigated using package signing. 

More reading

Here are some more writeups on package signing that are useful or that we found interesting:

Footnotes:

* GitHub allows commits and tag signing and will label them as verified-or-not, although there are no signatures/checksums available for release zip/tar archives. 

** GitLab allows commit signing and labels them as verified or not, but not for builds.

*** BitBucket Server allows commit and tag signing -- while Bitbucket Cloud does not yet -- but not for builds.

 

New call-to-action