Skip to content

Commit 77d2b82

Browse files
committed
Base64-encode cookie values embedded in JS
1 parent 9a1c70c commit 77d2b82

File tree

3 files changed

+27
-13
lines changed

3 files changed

+27
-13
lines changed

Lib/http/cookies.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -391,17 +391,21 @@ def __repr__(self):
391391
return '<%s: %s>' % (self.__class__.__name__, self.OutputString())
392392

393393
def js_output(self, attrs=None):
394+
import base64
394395
# Print javascript
395396
output_string = self.OutputString(attrs)
396397
if _has_control_character(output_string):
397398
raise CookieError("Control characters are not allowed in cookies")
399+
# Base64-encode value to avoid template
400+
# injection in cookie values.
401+
output_encoded = base64.b64encode(output_string.encode('utf-8')).decode("ascii")
398402
return """
399403
<script type="text/javascript">
400404
<!-- begin hiding
401-
document.cookie = \"%s\";
405+
document.cookie = atob(\"%s\");
402406
// end hiding -->
403407
</script>
404-
""" % (output_string.replace('"', r'\"'))
408+
""" % (output_encoded,)
405409

406410
def OutputString(self, attrs=None):
407411
# Build up our result

Lib/test/test_http_cookies.py

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
# Simple test suite for http/cookies.py
2-
2+
import base64
33
import copy
44
import unittest
55
import doctest
66
from http import cookies
77
import pickle
88
from test import support
9+
from test.test_ctypes.test_repr import base
910

1011

1112
class CookieTests(unittest.TestCase):
@@ -175,17 +176,19 @@ def test_load(self):
175176

176177
self.assertEqual(C.output(['path']),
177178
'Set-Cookie: Customer="WILE_E_COYOTE"; Path=/acme')
178-
self.assertEqual(C.js_output(), r"""
179+
cookie_encoded = base64.b64encode(b'Customer="WILE_E_COYOTE"; Path=/acme; Version=1').decode('ascii')
180+
self.assertEqual(C.js_output(), fr"""
179181
<script type="text/javascript">
180182
<!-- begin hiding
181-
document.cookie = "Customer=\"WILE_E_COYOTE\"; Path=/acme; Version=1";
183+
document.cookie = atob("{cookie_encoded}");
182184
// end hiding -->
183185
</script>
184186
""")
185-
self.assertEqual(C.js_output(['path']), r"""
187+
cookie_encoded = base64.b64encode(b'Customer="WILE_E_COYOTE"; Path=/acme').decode('ascii')
188+
self.assertEqual(C.js_output(['path']), fr"""
186189
<script type="text/javascript">
187190
<!-- begin hiding
188-
document.cookie = "Customer=\"WILE_E_COYOTE\"; Path=/acme";
191+
document.cookie = atob("{cookie_encoded}");
189192
// end hiding -->
190193
</script>
191194
""")
@@ -290,17 +293,19 @@ def test_quoted_meta(self):
290293

291294
self.assertEqual(C.output(['path']),
292295
'Set-Cookie: Customer="WILE_E_COYOTE"; Path=/acme')
293-
self.assertEqual(C.js_output(), r"""
296+
expected_encoded_cookie = base64.b64encode(b'Customer=\"WILE_E_COYOTE\"; Path=/acme; Version=1').decode('ascii')
297+
self.assertEqual(C.js_output(), fr"""
294298
<script type="text/javascript">
295299
<!-- begin hiding
296-
document.cookie = "Customer=\"WILE_E_COYOTE\"; Path=/acme; Version=1";
300+
document.cookie = atob("{expected_encoded_cookie}");
297301
// end hiding -->
298302
</script>
299303
""")
300-
self.assertEqual(C.js_output(['path']), r"""
304+
expected_encoded_cookie = base64.b64encode(b'Customer=\"WILE_E_COYOTE\"; Path=/acme').decode('ascii')
305+
self.assertEqual(C.js_output(['path']), fr"""
301306
<script type="text/javascript">
302307
<!-- begin hiding
303-
document.cookie = "Customer=\"WILE_E_COYOTE\"; Path=/acme";
308+
document.cookie = atob("{expected_encoded_cookie}");
304309
// end hiding -->
305310
</script>
306311
""")
@@ -391,13 +396,16 @@ def test_setter(self):
391396
self.assertEqual(
392397
M.output(),
393398
"Set-Cookie: %s=%s; Path=/foo" % (i, "%s_coded_val" % i))
399+
expected_encoded_cookie = base64.b64encode(
400+
("%s=%s; Path=/foo" % (i, "%s_coded_val" % i)).encode("ascii")
401+
).decode('ascii')
394402
expected_js_output = """
395403
<script type="text/javascript">
396404
<!-- begin hiding
397-
document.cookie = "%s=%s; Path=/foo";
405+
document.cookie = atob("%s");
398406
// end hiding -->
399407
</script>
400-
""" % (i, "%s_coded_val" % i)
408+
""" % (expected_encoded_cookie,)
401409
self.assertEqual(M.js_output(), expected_js_output)
402410
for i in ["foo bar", "foo@bar"]:
403411
# Try some illegal characters
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Base64-encode values when embedding cookies to JavaScript to avoid injection
2+
and escaping.

0 commit comments

Comments
 (0)