Skip to content

Commit 95b9ef8

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 95b9ef8

3 files changed

Lines changed: 11 additions & 6 deletions

File tree

rest_framework/templates/rest_framework/admin.html

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

246246
{% block script %}
247+
<script type="text/plain" id="drf_csrf_header_name">{{ csrf_header_name|default:'X-CSRFToken' }}</script>
248+
<script type="text/plain" id="drf_csrf_token">{{ csrf_token }}</script>
247249
<script>
248250
window.drf = {
249-
csrfHeaderName: "{{ csrf_header_name|default:'X-CSRFToken' }}",
250-
csrfToken: "{{ csrf_token }}"
251+
csrfHeaderName: document.getElementById('drf_csrf_header_name').textContent,
252+
csrfToken: document.getElementById('drf_csrf_token').textContent
251253
};
252254
</script>
253255
<script src="{% static "rest_framework/js/jquery-3.4.1.min.js" %}"></script>

rest_framework/templates/rest_framework/base.html

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,10 +287,13 @@ <h1>{{ name }}</h1>
287287
{% endif %}
288288

289289
{% block script %}
290+
291+
<script type="text/plain" id="drf_csrf_header_name">{{ csrf_header_name|default:'X-CSRFToken' }}</script>
292+
<script type="text/plain" id="drf_csrf_token">{% if request %}{{ csrf_token }}{% endif %}</script>
290293
<script>
291294
window.drf = {
292-
csrfHeaderName: "{{ csrf_header_name|default:'X-CSRFToken' }}",
293-
csrfToken: "{% if request %}{{ csrf_token }}{% endif %}"
295+
csrfHeaderName: document.getElementById('drf_csrf_header_name').textContent,
296+
csrfToken: document.getElementById('drf_csrf_token').textContent
294297
};
295298
</script>
296299
<script src="{% static "rest_framework/js/jquery-3.4.1.min.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'\bid="drf_csrf_token">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'\bid="drf_csrf_token"><', result.content.decode())

0 commit comments

Comments
 (0)