Repository: pypi/warehouse

Issue:
Set samesite=lax on session cookies
This is a strong defense-in-depth mechanism for protecting against CSRF. It's currently only respected by Chrome, but Firefox will add it as well.


Discussion:
This may be blocked on https://github.com/Pylons/pyramid/issues/2733
Thanks, @alex.

Yeah, after Pyramid supports this, Warehouse should add it.
I think we're blocked on a WebOb release, not pyramid support.
I think this is unblocked now that #3554 has been merged.

Resolving patch:
diff --git a/warehouse/sessions.py b/warehouse/sessions.py
--- a/warehouse/sessions.py
+++ b/warehouse/sessions.py
@@ -263,7 +263,6 @@ def _process_response(self, request, response):
                 max_age=self.max_age,
                 httponly=True,
                 secure=request.scheme == "https",
-                samesite=b"lax"
             )
 
 


Test patch:
diff --git a/requirements/tests.txt b/requirements/tests.txt
--- a/requirements/tests.txt
+++ b/requirements/tests.txt
@@ -224,9 +224,9 @@ urllib3==1.22 \
 waitress==1.1.0 \
     --hash=sha256:40b0f297a7f3af61fbfbdc67e59090c70dc150a1601c39ecc9f5f1d283fb931b \
     --hash=sha256:d33cd3d62426c0f1b3cd84ee3d65779c7003aae3fc060dee60524d10a57f05a9
-WebOb==1.8.0 \
-    --hash=sha256:ae809c05b667c3457a2937cdb4a7c7f07e90f26c651a340d37fdd1d5cf1fed27 \
-    --hash=sha256:6fca7aa39bd2f6d2ff71f15a22223ff256c91f60b1ab52dac0ab38dc6ea9142f
+WebOb==1.7.4 \
+    --hash=sha256:63f4220492476c5c716b615baed7bf3d27040b3105014375787160dee0943115 \
+    --hash=sha256:8d10af182fda4b92193113ee1edeb687ab9dc44336b37d6804e413f0240d40d9
 WebTest==2.0.29 \
     --hash=sha256:9136514159a2e76a21751bf4ab5d3371e539c8ada8b950fcf68e307d9e584a07 \
     --hash=sha256:dbbccc15ac2465066c95dc3a7de0d30cde3791e886ccbd7e91d5d2a2580c922d
diff --git a/tests/unit/test_sessions.py b/tests/unit/test_sessions.py
--- a/tests/unit/test_sessions.py
+++ b/tests/unit/test_sessions.py
@@ -497,7 +497,7 @@ def test_invalidated_deletes_save_non_secure(self, monkeypatch,
         )
         response = pretend.stub(
             set_cookie=pretend.call_recorder(
-                lambda cookie, data, max_age, httponly, secure, samesite: None
+                lambda cookie, data, max_age, httponly, secure: None
             )
         )
         session_factory._process_response(pyramid_request, response)
@@ -532,7 +532,6 @@ def test_invalidated_deletes_save_non_secure(self, monkeypatch,
                 max_age=12 * 60 * 60,
                 httponly=True,
                 secure=False,
-                samesite=b"lax",
             ),
         ]
 
diff --git a/tests/unit/utils/test_compression.py b/tests/unit/utils/test_compression.py
--- a/tests/unit/utils/test_compression.py
+++ b/tests/unit/utils/test_compression.py
@@ -14,7 +14,7 @@
 import pytest
 
 from pyramid.response import Response
-from webob.acceptparse import AcceptEncodingValidHeader, AcceptEncodingNoHeader
+from webob.acceptparse import Accept, NoAccept
 from webob.response import gzip_app_iter
 
 from warehouse.utils.compression import _compressor as compressor
@@ -54,7 +54,7 @@ def test_bails_if_content_encoding(self):
         ],
     )
     def test_sets_vary(self, vary, expected):
-        request = pretend.stub(accept_encoding=AcceptEncodingNoHeader())
+        request = pretend.stub(accept_encoding=NoAccept())
         response = Response(body=b"foo")
         response.vary = vary
 
@@ -66,9 +66,7 @@ def test_compresses_non_streaming(self):
         decompressed_body = b"foofoofoofoofoofoofoofoofoofoofoofoofoofoo"
         compressed_body = b"".join(list(gzip_app_iter([decompressed_body])))
 
-        request = pretend.stub(
-            accept_encoding=AcceptEncodingValidHeader("gzip")
-        )
+        request = pretend.stub(accept_encoding=Accept("gzip"))
         response = Response(body=decompressed_body)
         response.md5_etag()
 
@@ -85,9 +83,7 @@ def test_compresses_streaming(self):
         decompressed_body = b"foofoofoofoofoofoofoofoofoofoofoofoofoofoo"
         compressed_body = b"".join(list(gzip_app_iter([decompressed_body])))
 
-        request = pretend.stub(
-            accept_encoding=AcceptEncodingValidHeader("gzip")
-        )
+        request = pretend.stub(accept_encoding=Accept("gzip"))
         response = Response(app_iter=iter([decompressed_body]))
 
         compressor(request, response)
@@ -100,9 +96,7 @@ def test_compresses_streaming_with_etag(self):
         decompressed_body = b"foofoofoofoofoofoofoofoofoofoofoofoofoofoo"
         compressed_body = b"".join(list(gzip_app_iter([decompressed_body])))
 
-        request = pretend.stub(
-            accept_encoding=AcceptEncodingValidHeader("gzip")
-        )
+        request = pretend.stub(accept_encoding=Accept("gzip"))
         response = Response(app_iter=iter([decompressed_body]))
         response.etag = "foo"
 
@@ -117,9 +111,7 @@ def test_buffers_small_streaming(self):
         decompressed_body = b"foofoofoofoofoofoofoofoofoofoofoofoofoofoo"
         compressed_body = b"".join(list(gzip_app_iter([decompressed_body])))
 
-        request = pretend.stub(
-            accept_encoding=AcceptEncodingValidHeader("gzip")
-        )
+        request = pretend.stub(accept_encoding=Accept("gzip"))
         response = Response(
             app_iter=iter([decompressed_body]),
             content_length=len(decompressed_body),
@@ -132,9 +124,7 @@ def test_buffers_small_streaming(self):
         assert response.body == compressed_body
 
     def test_doesnt_compress_too_small(self):
-        request = pretend.stub(
-            accept_encoding=AcceptEncodingValidHeader("gzip")
-        )
+        request = pretend.stub(accept_encoding=Accept("gzip"))
         response = Response(body=b"foo")
 
         compressor(request, response)