[Python-Dev] security SIG? (was: Discussion overload)

Cory Benfield cory at lukasa.co.uk
Sat Jun 18 10:25:49 EDT 2016

> On 18 Jun 2016, at 11:38, Stephen J. Turnbull <stephen at xemacs.org> wrote:
> I see the security issue as a backyard swimming pool.  The law may say
> you must put a fence around it, but even 6 year olds can climb the
> fence, fall in the pool, and drown.  The hard-line security advocate
> position then is "the risk is a *kid's life*, backyard pools must be
> banned".  You have to sympathize with their honest and deep concern,
> but the community accepts that risk in the case of swimming pools.  I
> suspect the Python community at large is going to be happy with
> Larry's decision and the strategy of emphasizing the secrets module
> starting with 3.6.

I don’t think that’s really an accurate representation of any of the arguments put forward here. A better analogy is this:

- Right now, we have a fence around the neighbourhood swimming pool. This fence has a gate with a guard, and the guard prevents 6 year olds from getting through the gate.
- Kids can climb the fence (by using random.choice or something like it). The security community is mostly in agreement with the stdlib folks: we’re happy to say that this problem is best dealt with by educating children to not climb the fence (don’t use random.choice in a security context).
- In Python 3.4 and earlier, the guard on this gate will, in some circumstances, turn up to work drunk. The guard is very good at pretending to be sober, so you cannot tell just by looking that he’s drunk, but in this state he will let anyone through the gate. He sobers up fast, so it only matters if a child tries to get in very shortly after you open the swimming pool.
- In Python 3.5 we included a patch that, by accident, installed a breathalyser on the gate. Now the guard can only open the gate when he’s sober.
- The problem is that he cannot open the gate *for anyone* while he’s drunk. All entry to the pool stops if he shows up drunk.
- The security folks want to say “yes, this breathalyser is awesome, leave it in place, it should always have been there”.
- The compat folks want to say “the gate hasn’t had a breathalyser for years, and it represents a genuine inconvenience to adults who want to swim, so we need to remove it”.

We are not trying to take non-CSPRNGs away from you. We are not trying to remove the random module, we are not trying to say that everyone must use urandom for all cases. We totally agree with the consenting adults policy. We just believe that the number of people who have used os.urandom and actively wanted the Linux behaviour may well be zero, and is certainly a tiny fraction of the user base of os.urandom, whereas the number of people who have used os.urandom and expected it to produce safe random bytes is dramatically larger.

We believe that invisible risks are bad. We believe that it is difficult to meaningfully consent to behaviour you do not know about. And we believe that when your expectations are violated, it is better for the system to fail hard than to subtly degrade to a behaviour that puts you at risk, because one of these provides a trigger for action and one does not.

In the case of ‘consenting adults’: users cannot be said to have meaningfully consented to behaviours they do not understand. Consider urllib2 and PEP 476. Prior to Python 2.7.9, urllib2 did not validate TLS certificates. It *could*, if a user was willing to configure it to do so, but by default it did not. We could defend that behaviour under ‘consenting adults’: users *technically* consented to the behaviour by using the code. However, most of these users *passively* consented: their consent is inferred by their use of the API, but they have written no code that actively asserts their consent.

In Requests, we allow consenting adults to turn off cert verification if they want to, but they have to *actively* consent: they *have* to say verify=False. And they have to say it every time: we deliberately provide no global switch to turn off cert validation in Requests, you have to set verify=False every single time. This is very deliberate. If a user wants to shoot themselves in the foot they are welcome to do so, but we don’t hand the gun to the user pointed at their foot.

We’re arguing for the same here with os.urandom(). If you want the Linux default urandom behaviour, that’s fine, but we think that it’s surprising to people and that they should be forced to *actively ask* for that behaviour, rather than passively be given it.

The TL;DR is: consent is not the absence of saying no, it’s the presence of saying yes.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: Message signed with OpenPGP using GPGMail
URL: <http://mail.python.org/pipermail/python-dev/attachments/20160618/1b22458c/attachment.sig>

More information about the Python-Dev mailing list