[Distutils] PEP draft on PyPI/pip package signing

Donald Stufft donald at stufft.io
Tue Jul 29 00:26:21 CEST 2014

On July 28, 2014 at 5:57:54 PM, Giovanni Bajo (rasky at develer.com) wrote:
> Il giorno 28/lug/2014, alle ore 22:26, Donald Stufft ha scritto:  
> >
> > * Anyone able to defeat our TLS and is in a position to MITM a regular user
> > can simply supply their own trust file.
> Yes, though as you say, this is fixed by having the trust file signed.

If we're relying on an online key to sign this file, then we can trust that
online key to just sign everything and we don't need the authors to do anything
and we don't need a trust file.

> It can also be mitigated with certificate pinning and online sign of the trust file. Google+Chrome  
> has shown that pinning is very effective for this specific use-case (specific client  
> connecting to specific server).

If we're relying on pinned certificates in order to fetch the trust file
securely, then we can rely on it to securely transmit the package files.

> > * Anyone able to defeat our TLS and is in a position to MITM a package author
> > can simply register their own GPG key.
> The same happens with PEP458, for all packages but those in the “claimed" role (which  
> requires manual vetting; this can be added to my proposal as well).

Of course. I never said it didn't. The difference being that PEP 458 had a
plan for this, and the current proposal doesn't. This is a flaw with anything
that doesn't use some offline key or verification. However, as this proposal
copies more things from PEP 458, I struggle to see the reason for having it
over just doing PEP 458 (which I'm still not entirely sure is worth it).

> This is fixed by 2FA. Notice that implementing 2FA but *not* package signing is not enough  
> to fix this attack; the attacker in fact would still be able to simply modify a package  
> release in the transit, and the user would then 2FA-authorize a modified package without  
> realizing it.
> This is one of many examples in which 2FA collaborates with package signing to increase  
> security, and this is why I merged the two proposals; of course they can be split, but together  
> they achieve more.

No, 2FA does nothing for this, if you're in a position to MITM an exploited TLS
stream, you can just steal the session cookie which does not have a second factor.

> > * Anyone who has compromised an authors PyPI account can simply register their
> > own GPG key.
> The same happens with PEP458, for all packages but those in the “claimed” role.
> This is fixed again by 2FA. With notifications, there is a partial mitigation; delaying  
> 72 hours for popular packages is also a good mitigation.
> For this specific scenario (attacker who has compromised the PyPI account), I agree  
> that package signing is not specifically useful; but it is also expected as a PyPI account  
> is the only way we associate an author with a package, so it makes sense that end-to-end  
> security is broken.

To be clear, the point of the claimed role is to be the target security level
for all people to be in. The other roles exist primarily to limit the trust on
TLS and to enable moving from the unclaimed to claimed role. If PEP 458 didn't
have the claimed role you'd see me being strongly -1 on it as well.

> > * Fastly (which is effictively a persistent MITM) could simply modify traffic
> > to register their own GPG key.
> True. This is also fixed by PyPI online signing of the trust file.

At which point, why don't we just trust that key completely and let it sign
all the packages?

> > * Anyone who has compromised PyPI can simply generate their own trust file
> > with their own keys.
> Yes, this scenario is well analyzed in my PEP, including mitigations and likely attack  
> vectors.
> I don’t see PEP458 solving this, but this is where my understanding of it gets fuzzier;  
> compromising PyPI let you compromise all online roles, as far as I can tell; and at that  
> point, you can compromise timestamp, consistent-snapshot and recently-claimed roles  
> at the same time (which the PEP states that must be online), and this allows you for serving  
> malicious updates, do freeze attacks and whatnot.

Correct, any of the online keys can be compromised, the real benefit of TUF (as
far as end to end security is concerned) is in the claimed role.

> The only real additional security of PEP458 seems like the manual step of vetting maintainers  
> keys, thus freezing them. If this is a wanted improvement, it can be easily added to my  
> proposal a well with a very slight modification. The hardest part here is how the vet process  
> should work; it’s a VERY complicated process to pull off in the real world without being  
> subject to e.g.: social engineering; if the process is worked out, it’s trivial to modify  
> my proposal to handle this as well.

Again, as this proposal copies more from TUF I fail to see it’s benefit over TUF.

> > Now it is true that if we sign the trust file with a key that is stored on
> > PyPI, then the first one of those cases is no longer possible. However the
> > remaining three are still there. This means we are still effectively relying
> > on the security of TLS and thus we've not really gained anything except
> > additional complexity.
> I think you’re oversimplifying the conclusion. There are many possible attack scenarios,  
> and my proposal (as a whole) fixes many of them, as described in my threat model.

I’m not oversimplifying it.

> Also it looks like you’re also ignoring the additional layer of manually handling a local  
> copy of the trust file. This is very useful for some scenarios like unattended deployments  
> and company indexes, and protects against additional attacks (e.g.: shadowing of private  
> packages in PyPI). I’ve just updated the PEP to describe these attacks.
> Can you please explain which of your proposed attacks is better handled by PEP458?

All of them? They are more or less completely mitigated once someone is safely
in the claimed role.

> With a conservative average of 60 bytes per package, the trust file would measure around 
> 3 mb today. Assuming all authors rotate GPG keys every year, and package numbers that  
> grow 50% every year, the trust-file would reach 170Mb in 10 years. Introducing a way to  
> reset (“rotate”) the file every 5 years seems more than sufficient.
> You have a solid point on DoS, this is something that must be handled through throttling  
> I guess. I don’t see TUF fixing this either; isn’t there a single ever-growing targets.txt?

The targets.txt can be broken up fairly trivially if I recall. In fact I am
pretty sure they do this for the unclaimed role and they stick them in
different bins.

> > Implement 2FA/Better Authentication
> > -----------------------------------
> >
> > Absolutely, we don't need a PEP to do this, we just need to do it. It's on my
> > personal TODO list but other things have had higher priority thus far.
> Maybe not a PEP, but some discussion is needed.
> Would you prefer patches against PyPI or warehouse? Would you evaluate a simpler solution  
> using a third-party 2FA provider (e.g.: Authy or Duo Security) that could be talked into  
> a PSF sponsorship, or would you prefer an in-house solution? If in-house, is it OK to go  
> with a standard OATH TOTP with QR Code for provisioning, or you prefer to also have alternatives  
> like SMS? How do you propose to handle recovery for a lost token (e.g.: stolen smartphone  
> with no backup)? Would you ask for the token for all web logins? What about package uploads:  
> should distutils be modified to also ask for 2FA in interactive mode on the terminal,  
> to confirm a package release?

1. PyPI v Warehouse, if you want to implement it now, PyPI and Warehouse. I
   haven't done it yet because I don't want to implement it on PyPI-Legacy and
   I'm waiting until Warehouse is deployed.

2. I've looked at Duo Security. I'm not completely opposed to it, I know there
   are some who are. It has nice feature sets especially with alternative
   means of 2FA.

3. If we implement our own it'll be TOTP, probably with a QR code yes.

4. Backup codes should exist yes.

5. If a person has 2FA enabled on their account it should be required for any
   web login. Packages should also be able to mandate that a person has 2FA for
   manipulating that package.

6. distutils is the hard part here. We can't modify distutils for 2.6, and for
   2.7, 3.2, 3.3, and 3.4 it'll be hard to do.

Donald Stufft
PGP: 0x6E3CBCE93372DCFA // 7C6B 7C5D 5E2B 6356 A926 F04F 6E3C BCE9 3372 DCFA

More information about the Distutils-SIG mailing list