Skip to content

Commit 0d6dbf8

Browse files
authored
Merge pull request #178 from mozilla/fix-unwrap-script-re
fix unwrap script re
2 parents 3659ddc + 70f65b8 commit 0d6dbf8

File tree

6 files changed

+93
-9
lines changed

6 files changed

+93
-9
lines changed

CHANGES

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Next
99
- Add project urls to setup.py
1010
- Drop support for EOL Python <3.6 and Django <2.2 versions
1111
- Rename default branch to main
12+
- Fix capturing brackets in script template tags
1213

1314
3.7
1415
===

csp/tests/test_jinja_extension.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,22 @@ def test_nested_script_tags_are_removed(self):
7777
'var hello=\'world\';</script>')
7878

7979
self.assert_template_eq(*self.process_templates(tpl, expected))
80+
81+
def test_regex_captures_script_content_including_brackets(self):
82+
"""
83+
Ensure that script content get captured properly.
84+
Especially when using angle brackets."""
85+
tpl = """
86+
{% script %}
87+
<script type="text/javascript">
88+
let capture_text = "<script></script>"
89+
</script>
90+
{% endscript %}
91+
"""
92+
93+
expected = (
94+
'<script nonce="{}">'
95+
'let capture_text = "<script></script>"'
96+
'</script>')
97+
98+
self.assert_template_eq(*self.process_templates(tpl, expected))

csp/tests/test_templatetags.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,23 @@ def test_nested_script_tags_are_removed(self):
7676
'var hello=\'world\';</script>')
7777

7878
self.assert_template_eq(*self.process_templates(tpl, expected))
79+
80+
def test_regex_captures_script_content_including_brackets(self):
81+
"""
82+
Ensure that script content get captured properly.
83+
Especially when using angle brackets."""
84+
tpl = """
85+
{% load csp %}
86+
{% script %}
87+
<script type="text/javascript">
88+
let capture_text = "<script></script>"
89+
</script>
90+
{% endscript %}
91+
"""
92+
93+
expected = (
94+
'<script nonce="{}">'
95+
'let capture_text = "<script></script>"'
96+
'</script>')
97+
98+
self.assert_template_eq(*self.process_templates(tpl, expected))

csp/tests/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class ScriptTestBase(object):
2424
def assert_template_eq(self, tpl1, tpl2):
2525
aaa = tpl1.replace('\n', '').replace(' ', '')
2626
bbb = tpl2.replace('\n', '').replace(' ', '')
27-
assert aaa == bbb
27+
assert aaa == bbb, "{} != {}".format(aaa, bbb)
2828

2929
def process_templates(self, tpl, expected):
3030
request = rf.get('/')

csp/utils.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,9 +155,19 @@ def _async_attr_mapper(attr_name, val):
155155
ATTR_FORMAT_STR = ''.join(['{{{}}}'.format(a) for a in SCRIPT_ATTRS])
156156

157157

158+
_script_tag_contents_re = re.compile(
159+
r"""<script # match the opening script tag
160+
[\s|\S]*?> # minimally match attrs and spaces in opening script tag
161+
([\s|\S]+) # greedily capture the script tag contents
162+
</script> # match the closing script tag
163+
""",
164+
re.VERBOSE,
165+
)
166+
167+
158168
def _unwrap_script(text):
159169
"""Extract content defined between script tags"""
160-
matches = re.search(r'<script[\s|\S]*>([\s|\S]+?)</script>', text)
170+
matches = re.search(_script_tag_contents_re, text)
161171
if matches and len(matches.groups()):
162172
return matches.group(1).strip()
163173

docs/nonce.rst

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,32 @@ This library contains an optional context processor, adding ``csp.context_proces
4242

4343
.. note::
4444

45-
If you're making use of ``csp.extensions.NoncedScript`` you need to have ``jinja2>=2.9.6`` installed, so please make sure to either use ``django-csp[jinja2]`` in your requirements or define it yourself.
45+
If you're making use of ``csp.extensions.NoncedScript`` you need to have ``jinja2>=2.9.6`` installed, so please make sure to either use ``django-csp[jinja2]`` in your requirements or define it yourself.
4646

47-
Since it can be easy to forget to include the ``nonce`` property in a script tag, there is also a ``script`` template tag available for both Django templates and Jinja environments.
47+
48+
It can be easy to forget to include the ``nonce`` property in a script tag, so there is also a ``script`` template tag available for both Django templates and Jinja environments.
4849

4950
This tag will output a properly nonced script every time. For the sake of syntax highlighting, you can wrap the content inside of the ``script`` tag in ``<script>`` html tags, which will be subsequently removed in the rendered output. Any valid script tag attributes can be specified and will be forwarded into the rendered html.
5051

51-
Django:
52+
53+
Django Templates
54+
----------------
55+
56+
Add the CSP template tags to the TEMPLATES section of your settings file:
57+
58+
.. code-block:: python
59+
60+
TEMPLATES = [
61+
{
62+
"OPTIONS": {
63+
'libraries': {
64+
'csp': 'csp.templatetags.csp',
65+
}
66+
},
67+
}
68+
]
69+
70+
Then load the ``csp`` template tags and use ``script`` in the template:
5271

5372
.. code-block:: jinja
5473
@@ -60,9 +79,24 @@ Django:
6079
{% endscript %}
6180
6281
63-
Jinja:
82+
Jinja
83+
-----
84+
85+
Add ``csp.extensions.NoncedScript`` to the TEMPLATES section of your settings file:
86+
87+
.. code-block:: python
88+
89+
TEMPLATES = [
90+
{
91+
'BACKEND':'django.template.backends.jinja2.Jinja2',
92+
'OPTIONS': {
93+
'extensions': [
94+
'csp.extensions.NoncedScript',
95+
],
96+
}
97+
}
98+
]
6499
65-
(assumes ``csp.extensions.NoncedScript`` is added to the jinja extensions setting)
66100
67101
.. code-block:: jinja
68102
@@ -72,9 +106,9 @@ Jinja:
72106
</script>
73107
{% endscript %}
74108
75-
Will output -
109+
110+
Both templates output the following with a different nonce:
76111

77112
.. code-block:: html
78113

79114
<script nonce='123456' type="application/javascript" async=false>var hello='world';</script>
80-

0 commit comments

Comments
 (0)