Python Package Management for the Paranoid

Anthony Shaw
Python Pandemonium
Published in
4 min readJun 4, 2017

This tweet by Kenneth Reitz (author of many Python packages), caught my eye the other week

Kenneth is highlighting a significant security risk to those packages, that some malicious person could compromise his account, publish requests and anyone that installs the package would be running arbitrary code. Yikes.

I’m a little security conscious (paranoid) when it comes to these things, sign my git commits and packages using a key that is published to the repo. It’s worth noting that this takes a while to setup and I know that most people haven’t (because the “verified” label in GitHub is a lesser-spotted animal).

Creating an online key

PGP and GPG are confusingly similar. PGP was originally proprietary, but the OpenPGP standard came and was later widely adopted. You can choose to use either, for my case I use GPG.

$ gpg --gen-key

Choose RSA, 4096 bit encryption and enter your primary email address (this also needs to be one of your verified emails registered with GitHub).

Upload that key to https://pgp.mit.edu by getting it’s ID gpg --list-secret-keys --keyid-format LONG and then exporting the text from gpg --armor --export <your key id> . Simply copy+paste the text into their website and your public key will be public domain. Your key should have others verify it, as well as your identity via a signing exchange, but that’s too much detail for this article.

Configuring GitHub

1. Stop using HTTPS remotes

Moving completely to 2FA auth with GitHub needs a call to git remote get-url origin (assuming your remote is called origin) for repos that you need permissions to pull or push to. This will tell you whether you’re using HTTPS or git (SSH) to connect. You can replace an existing URL with a SSH address easily by calling git remote set-url origin git@github.com:myuser/myrepo.git

2. Enable 2FA

In your GitHub profile, enable two-factor. This stops you from ever having your compromised password used to change projects, upload dodgy code, etc. It takes 2 minutes.

3. Upload your GPG key to GitHub

In the SSH and GPG keys section, share the public key with GitHub (the asc file) so that your commits are verified (I’ll explain how to do this later).

Signing in Git

Earlier we created a GPG key (or maybe you already had one). Now we need to tell Git to use it. Find the long identifier of the key with this command gpg --list-secret-keys --keyid-format LONG and paste that into your git configuration as so,

git config --global user.signingkey <Long key id>

Unless you tell Git, it won’t sign your commits. There are flags for signing commits, merges and tags. git tag --sign, git commit -D and git merge -D

People tend to forget, so it makes sense to set a shell alias for git commit to be git commit -D , likewise with git merge.

Try committing and pushing some code up to GitHub. If all has been done correctly you should see a nice green tick

PyPi and PGP

In PyPi, you can upload the short ID for your GPG key into the profile,

Signing packages is pretty straightforward, when you publish the source and wheel, include the identity and the request to sign before upload.

python setup.py sdist bdist_wheel upload --sign --identity <your PGP key id>

Full details on how to sign using the Python API or check signed releases can be found here http://pythonhosted.org/distlib/tutorial.html#signing-a-distribution

Published, signed source packages should have MD5 and PGP (asc files) in PyPi. This is shown in the pgp link in brackets.

--

--

Anthony Shaw
Python Pandemonium

Group Director of Talent at Dimension Data, father, Christian, Python Software Foundation Fellow, Apache Foundation Member.