Skip to content

Commit 9eda043

Browse files
committed
Separate CSRF data from executed javascript code to support CSP
By moving dynamic data into a safe non-executed block and keeping scripts static, developers can add sha256 hash to CSP exceptions.
1 parent c9f06bf commit 9eda043

3 files changed

Lines changed: 16 additions & 10 deletions

File tree

rest_framework/templates/rest_framework/admin.html

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -244,11 +244,14 @@ <h4 class="modal-title" id="myModalLabel">{{ error_title }}</h4>
244244
{% endif %}
245245

246246
{% block script %}
247+
<script type="application/json" id="drf_csrf">{{
248+
{
249+
"csrfHeaderName": csrf_header_name|default:'X-CSRFToken',
250+
"csrfToken": csrfToken
251+
} | tojson
252+
}}</script>
247253
<script>
248-
window.drf = {
249-
csrfHeaderName: "{{ csrf_header_name|default:'X-CSRFToken' }}",
250-
csrfToken: "{{ csrf_token }}"
251-
};
254+
window.drf = JSON.parse(document.getElementById('drf_csrf').innerHTML);
252255
</script>
253256
<script src="{% static "rest_framework/js/jquery-3.4.1.min.js" %}"></script>
254257
<script src="{% static "rest_framework/js/ajax-form.js" %}"></script>

rest_framework/templates/rest_framework/base.html

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -287,11 +287,14 @@ <h1>{{ name }}</h1>
287287
{% endif %}
288288

289289
{% block script %}
290+
<script type="application/json" id="drf_csrf">{{
291+
{
292+
"csrfHeaderName": csrf_header_name|default:'X-CSRFToken',
293+
"csrfToken": csrfToken if request else None
294+
} | tojson
295+
}}</script>
290296
<script>
291-
window.drf = {
292-
csrfHeaderName: "{{ csrf_header_name|default:'X-CSRFToken' }}",
293-
csrfToken: "{% if request %}{{ csrf_token }}{% endif %}"
294-
};
297+
window.drf = JSON.parse(document.getElementById('drf_csrf').innerHTML);
295298
</script>
296299
<script src="{% static "rest_framework/js/jquery-3.4.1.min.js" %}"></script>
297300
<script src="{% static "rest_framework/js/ajax-form.js" %}"></script>

tests/test_templates.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66
def test_base_template_with_context():
77
context = {'request': True, 'csrf_token': 'TOKEN'}
88
result = render({}, 'rest_framework/base.html', context=context)
9-
assert re.search(r'\bcsrfToken: "TOKEN"', result.content.decode())
9+
assert re.search(r'\b"csrfToken": "TOKEN"', result.content.decode())
1010

1111

1212
def test_base_template_with_no_context():
1313
# base.html should be renderable with no context,
1414
# so it can be easily extended.
1515
result = render({}, 'rest_framework/base.html')
1616
# note that this response will not include a valid CSRF token
17-
assert re.search(r'\bcsrfToken: ""', result.content.decode())
17+
assert re.search(r'\b"csrfToken": ""', result.content.decode())

0 commit comments

Comments
 (0)