Repository: urllib3/urllib3

Issue:
Really don't spam InsecurePlatformWarning
urllib3 should configure its warnings using append=True to avoid overriding the user's preferences as specified with python -W or PYTHONWARNINGS.

If this issue were fixed, the user could work around pypa/pip#2681 with

```
export PYTHONWARNINGS="ignore:A true SSLContext object is not available"
```

Additionally, the urllib3 docs are very unclear about why this is considered worth warning the end user about, particularly given that adding this strange message has effectively introduced a bug in hundreds of other projects.



Discussion:
For what it's worth, the security concerns:
- On Python 2.6 urllib3 cannot set the allowed ciphers, making it possible that you'll connect using an insecure cipher using whatever the default is (most likely includes `EXPORT` ciphers).
- On Python <2.7.9 and 2.6 urllib3 cannot disable the use of SSLv2 or SSLv3 without pinning to explicitly TLSv1.0 (and it cannot pin to TLSv1.1 or TLSv1.2), making it possible that you'll connect using an insecure version of the SSL/TLS protocol.
- On Python <2.7.9 and 2.6 urllib3 cannot disable TLS Compression, making it possible for attackers to possibly determine the contents of an encrypted stream using the CRIME attack.
- On Python <2.7.9 and 2.6 urllib3 cannot set specific options, this is a big deal because it's caused requests to have to rollback the removal of the weak 1024 bit roots because it could not set the setting that instructs OpenSSL to prefer a shorter, trusted path over the entire path that the server provided.
- On Python <2.7.9 and 2.6 urllib3 cannot use SNI, this is less directly a security sensitive item, however the lack of SNI can cause people to disable ssl verification on sites that require SNI which means that missing SNI indirectly incentivizes people to downgrade their security.

> particularly given that adding this strange message has effectively introduced a bug in hundreds of other projects.

I'm sorry, but this sentiment is ridiculous. The correct sentiment is "this strange message has revealed a bug in hundreds of other projects".

Not having an `SSLContext` object exposes users to security risks without giving us any tools to mitigate them. Users have every right to know that the projects they use are not secure, and developers should be aware that it is within their power to secure their projects.

However, I do think the `append=True` approach is a reasonable one. The purpose of warnings is always that users should be able to turn them off, and generally speaking I'm ok with making that possible.

Thanks for providing the list of security concerns (and for your efforts improving Python TLS support in general). Secure configuration doesn't seem impossible (on Python 2.7) under those constraints if you trust the server configuration, e.g. by specifying TLS and AES-GCM and downloading from PyPI, though I appreciate it's hard to assure security in a general public PKI setting.  I presume you can pin TLS 1.2 if you know the server supports it?  Re. requests, I'd have thought the 1024 bit roots could have been added only on weaker platforms, but I haven't seen the issue.

Anyway, I look forward to seeing append=True in a release.

> urllib3 should configure its warnings using append=True to avoid overriding the user's preferences as specified with python -W or PYTHONWARNINGS.

That sounds good.

> Additionally, the urllib3 docs are very unclear about why this is considered worth warning the end user about...

@dstufft Thanks for going over that! Would indeed be swell to include this in our security section of the docs, though I assume that even this list is not exhaustive.

@tlynn Would you like to make these changes? I'd be happy to merge. :)


Resolving patch:
diff --git a/urllib3/__init__.py b/urllib3/__init__.py
--- a/urllib3/__init__.py
+++ b/urllib3/__init__.py
@@ -57,9 +57,10 @@ def add_stderr_logger(level=logging.DEBUG):
 
 import warnings
 # SecurityWarning's always go off by default.
-warnings.simplefilter('always', exceptions.SecurityWarning)
+warnings.simplefilter('always', exceptions.SecurityWarning, append=True)
 # InsecurePlatformWarning's don't vary between requests, so we keep it default.
-warnings.simplefilter('default', exceptions.InsecurePlatformWarning)
+warnings.simplefilter('default', exceptions.InsecurePlatformWarning,
+                      append=True)
 
 def disable_warnings(category=exceptions.HTTPWarning):
     """


Test patch: