mirror of
https://github.com/python/cpython.git
synced 2026-05-06 04:37:33 -04:00
[3.14] gh-90309: Base64-encode cookie values embedded in JS (GH-148889)
(cherry picked from commit 76b3923d68)
Co-authored-by: Seth Larson <seth@python.org>
This commit is contained in:
committed by
GitHub
parent
dd9a77ff2e
commit
f795e04204
+6
-2
@@ -391,17 +391,21 @@ class Morsel(dict):
|
||||
return '<%s: %s>' % (self.__class__.__name__, self.OutputString())
|
||||
|
||||
def js_output(self, attrs=None):
|
||||
import base64
|
||||
# Print javascript
|
||||
output_string = self.OutputString(attrs)
|
||||
if _has_control_character(output_string):
|
||||
raise CookieError("Control characters are not allowed in cookies")
|
||||
# Base64-encode value to avoid template
|
||||
# injection in cookie values.
|
||||
output_encoded = base64.b64encode(output_string.encode('utf-8')).decode("ascii")
|
||||
return """
|
||||
<script type="text/javascript">
|
||||
<!-- begin hiding
|
||||
document.cookie = \"%s\";
|
||||
document.cookie = atob(\"%s\");
|
||||
// end hiding -->
|
||||
</script>
|
||||
""" % (output_string.replace('"', r'\"'))
|
||||
""" % (output_encoded,)
|
||||
|
||||
def OutputString(self, attrs=None):
|
||||
# Build up our result
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Simple test suite for http/cookies.py
|
||||
|
||||
import base64
|
||||
import copy
|
||||
import unittest
|
||||
import doctest
|
||||
@@ -152,17 +152,19 @@ class CookieTests(unittest.TestCase):
|
||||
|
||||
self.assertEqual(C.output(['path']),
|
||||
'Set-Cookie: Customer="WILE_E_COYOTE"; Path=/acme')
|
||||
self.assertEqual(C.js_output(), r"""
|
||||
cookie_encoded = base64.b64encode(b'Customer="WILE_E_COYOTE"; Path=/acme; Version=1').decode('ascii')
|
||||
self.assertEqual(C.js_output(), fr"""
|
||||
<script type="text/javascript">
|
||||
<!-- begin hiding
|
||||
document.cookie = "Customer=\"WILE_E_COYOTE\"; Path=/acme; Version=1";
|
||||
document.cookie = atob("{cookie_encoded}");
|
||||
// end hiding -->
|
||||
</script>
|
||||
""")
|
||||
self.assertEqual(C.js_output(['path']), r"""
|
||||
cookie_encoded = base64.b64encode(b'Customer="WILE_E_COYOTE"; Path=/acme').decode('ascii')
|
||||
self.assertEqual(C.js_output(['path']), fr"""
|
||||
<script type="text/javascript">
|
||||
<!-- begin hiding
|
||||
document.cookie = "Customer=\"WILE_E_COYOTE\"; Path=/acme";
|
||||
document.cookie = atob("{cookie_encoded}");
|
||||
// end hiding -->
|
||||
</script>
|
||||
""")
|
||||
@@ -267,17 +269,19 @@ class CookieTests(unittest.TestCase):
|
||||
|
||||
self.assertEqual(C.output(['path']),
|
||||
'Set-Cookie: Customer="WILE_E_COYOTE"; Path=/acme')
|
||||
self.assertEqual(C.js_output(), r"""
|
||||
expected_encoded_cookie = base64.b64encode(b'Customer=\"WILE_E_COYOTE\"; Path=/acme; Version=1').decode('ascii')
|
||||
self.assertEqual(C.js_output(), fr"""
|
||||
<script type="text/javascript">
|
||||
<!-- begin hiding
|
||||
document.cookie = "Customer=\"WILE_E_COYOTE\"; Path=/acme; Version=1";
|
||||
document.cookie = atob("{expected_encoded_cookie}");
|
||||
// end hiding -->
|
||||
</script>
|
||||
""")
|
||||
self.assertEqual(C.js_output(['path']), r"""
|
||||
expected_encoded_cookie = base64.b64encode(b'Customer=\"WILE_E_COYOTE\"; Path=/acme').decode('ascii')
|
||||
self.assertEqual(C.js_output(['path']), fr"""
|
||||
<script type="text/javascript">
|
||||
<!-- begin hiding
|
||||
document.cookie = "Customer=\"WILE_E_COYOTE\"; Path=/acme";
|
||||
document.cookie = atob("{expected_encoded_cookie}");
|
||||
// end hiding -->
|
||||
</script>
|
||||
""")
|
||||
@@ -368,13 +372,16 @@ class MorselTests(unittest.TestCase):
|
||||
self.assertEqual(
|
||||
M.output(),
|
||||
"Set-Cookie: %s=%s; Path=/foo" % (i, "%s_coded_val" % i))
|
||||
expected_encoded_cookie = base64.b64encode(
|
||||
("%s=%s; Path=/foo" % (i, "%s_coded_val" % i)).encode("ascii")
|
||||
).decode('ascii')
|
||||
expected_js_output = """
|
||||
<script type="text/javascript">
|
||||
<!-- begin hiding
|
||||
document.cookie = "%s=%s; Path=/foo";
|
||||
document.cookie = atob("%s");
|
||||
// end hiding -->
|
||||
</script>
|
||||
""" % (i, "%s_coded_val" % i)
|
||||
""" % (expected_encoded_cookie,)
|
||||
self.assertEqual(M.js_output(), expected_js_output)
|
||||
for i in ["foo bar", "foo@bar"]:
|
||||
# Try some illegal characters
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
Base64-encode values when embedding cookies to JavaScript using the
|
||||
:meth:`http.cookies.BaseCookie.js_output` method to avoid injection
|
||||
and escaping.
|
||||
Reference in New Issue
Block a user