Provide a pythonic way to inject your won where() function

If a module called `requests_extension` define a function called
where(); this function will be used instead of requests.certs.where()


Thanks for this!

I'm -0.5 on this change, because I believe it to be a security risk. It is upsettingly easy to create a situation where such a module is installed that defines a `where()` function that returns arbitrary certificates, and such behaviour would not be noticed. Monkeypatching makes this behaviour harder (though not impossible).

I'm going to wait until @sigmavirus24 weighs in. =)


Today requests.get() accept a parameter `verify` that allows to pass arbitrary ca-certs.
So the vulnerability is somehow already there isn't it ?


The difference is how the vulnerability is attacked. For `verify`, you have to control the parameters being passed to a single `requests` call. This means if I write code myself that calls `requests.get()`, I _know_ whether or not my certs are getting validated.

With this patch, I would _not_ know that unless I scoured the imported packages before I called `requests.get()` to confirm that `requests_extension` package existed. If one was installed on my system for any reason, even if I set `verify=True` explicitly I would still tacitly accept certs that I shouldn't.


If you let your user write python modules like request_extensions.py, then they can call `request.get(verify=False)` easily.
If you do not allow your user to write code, then they can not write nor install nor load request_extensions.py.
I mean, it is either secure or not. There is no "in between" situation like you describe, where you allow user to write python code and assume that all `request.get(verify=True)` will be honoured.


I think you're totally misunderstanding me.

Suppose you install `pip`. `pip` uses Requests and verifies all TLS certificates. In a clean Python install, you know that all is well and that you cannot be Man-in-the-Middle attacked.

With your suggestion, if I can get access to your computer I can install my own `requests_extension` package that adds my own self-signed root certificate to your list of certificates. This will immediately start affecting `pip`, and indeed any other script on your machine that uses Requests: they'll all start loading my own certificates.

Obviously, for me to do that I would have required access to your machine, so let me provide a worse example. Suppose I'm Generic Evil Corp, and I want to ship a Python API client. I build it on top of requests, but I don't want to bother having to buy a TLS certificate, so I self-sign one and then add my own `requests_extension` module to my dependencies. Anyone who installs my module now quietly accepts my TLS certificate as 'trusted', and _they don't know they're doing it_.

In essence, the difference is scope. In your case, I have to verify that I've never installed a `requests_extension` package, because if I have it affects _everything_. There is no compelling use-case for this that I can see that justifies this enormous risk.

I'm actually upgrading my objection to -1. The more I think about it the worse it sounds.


Oh man, I just keep thinking of ways this can be made worse. The surface area of ways to attack certificate validation here is _enormous_. Just think of the sheer number of ways Python modules can be imported or installed: this is totally terrifying. I'm going further than -1, I'm closing this. Thanks for providing the work, but I think the danger inherent in this totally outweighs any advantage it has.


Beyond the security implications that @Lukasa has already outlined, I am 100% opposed to the hard coding of an import statement of a module that is not maintained by one of us. This provides a rich opportunity for someone to make a package on PyPI that subtly hides this and installs a package named `requests_extension`. Let's say I added that to a package I already distribute, then I could, by someone installing an otherwise innocuous package, totally take control of certificate discovery on their installation without their knowledge.

You claim requests is insecure already but this would introduce the largest of backdoors into requests as it exists now.

Thank you for your contribution but we can not accept it in good conscience.

Furthermore, I don't feel there is further need for discussion on this issue.


Actually, one last comment:

This is not pythonic by any means. The pythonic way to handle this would still be unacceptable.


thank you @Lukasa I understand the use case you pointed now,
and agreed it was a bad idea to do it that way.

What about adding built-in operating system flavor instead ?
Most package maintainer of requests for major linux distributions just hardcode the path to the main cert file like `/etc/ssl/certs/ca-certificates.crt` for debian based distributions for instance.

Then `requests` could provide out of the box some of those locations, if we can guess reliably the type of distribution requests is running on.

How does it sounds ?


@ticosax we experimented with including a list of popular locations and just kept receiving pull requests to add it for more and more obscure repositories so we removed them entirely and rely on what we have now. It is highly unlikely we'll be moving back to that model


Fair enough.
thx for replying


Thank you for contributing @ticosax