mirror of
				https://github.com/encode/django-rest-framework.git
				synced 2025-11-04 01:47:59 +03:00 
			
		
		
		
	Avoid inline script execution for injecting CSRF token (#7016)
Scripts with type="application/json" or "text/plain" are not executed, so we can use them to inject dynamic CSRF data, without allowing inline-script execution in Content-Security-Policy.
This commit is contained in:
		
							parent
							
								
									f0095b4de2
								
							
						
					
					
						commit
						6ec6ddea9b
					
				| 
						 | 
				
			
			@ -38,6 +38,7 @@ function sameOrigin(url) {
 | 
			
		|||
    !(/^(\/\/|http:|https:).*/.test(url));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
window.drf = JSON.parse(document.getElementById('drf_csrf').textContent);
 | 
			
		||||
var csrftoken = window.drf.csrfToken;
 | 
			
		||||
 | 
			
		||||
$.ajaxSetup({
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -244,11 +244,11 @@
 | 
			
		|||
      {% endif %}
 | 
			
		||||
 | 
			
		||||
      {% block script %}
 | 
			
		||||
        <script>
 | 
			
		||||
          window.drf = {
 | 
			
		||||
            csrfHeaderName: "{{ csrf_header_name|default:'X-CSRFToken' }}",
 | 
			
		||||
            csrfToken: "{{ csrf_token }}"
 | 
			
		||||
          };
 | 
			
		||||
        <script type="application/json" id="drf_csrf">
 | 
			
		||||
          {
 | 
			
		||||
            "csrfHeaderName": "{{ csrf_header_name|default:'X-CSRFToken' }}",
 | 
			
		||||
            "csrfToken": "{{ csrf_token }}"
 | 
			
		||||
          }
 | 
			
		||||
        </script>
 | 
			
		||||
        <script src="{% static "rest_framework/js/jquery-3.5.1.min.js" %}"></script>
 | 
			
		||||
        <script src="{% static "rest_framework/js/ajax-form.js" %}"></script>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -287,11 +287,11 @@
 | 
			
		|||
    {% endif %}
 | 
			
		||||
 | 
			
		||||
    {% block script %}
 | 
			
		||||
      <script>
 | 
			
		||||
        window.drf = {
 | 
			
		||||
          csrfHeaderName: "{{ csrf_header_name|default:'X-CSRFToken' }}",
 | 
			
		||||
          csrfToken: "{% if request %}{{ csrf_token }}{% endif %}"
 | 
			
		||||
        };
 | 
			
		||||
      <script type="application/json" id="drf_csrf">
 | 
			
		||||
        {
 | 
			
		||||
          "csrfHeaderName": "{{ csrf_header_name|default:'X-CSRFToken' }}",
 | 
			
		||||
          "csrfToken": "{% if request %}{{ csrf_token }}{% endif %}"
 | 
			
		||||
        }
 | 
			
		||||
      </script>
 | 
			
		||||
      <script src="{% static "rest_framework/js/jquery-3.5.1.min.js" %}"></script>
 | 
			
		||||
      <script src="{% static "rest_framework/js/ajax-form.js" %}"></script>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,7 @@ from django.shortcuts import render
 | 
			
		|||
def test_base_template_with_context():
 | 
			
		||||
    context = {'request': True, 'csrf_token': 'TOKEN'}
 | 
			
		||||
    result = render({}, 'rest_framework/base.html', context=context)
 | 
			
		||||
    assert re.search(r'\bcsrfToken: "TOKEN"', result.content.decode())
 | 
			
		||||
    assert re.search(r'"csrfToken": "TOKEN"', result.content.decode())
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_base_template_with_no_context():
 | 
			
		||||
| 
						 | 
				
			
			@ -14,4 +14,4 @@ def test_base_template_with_no_context():
 | 
			
		|||
    # so it can be easily extended.
 | 
			
		||||
    result = render({}, 'rest_framework/base.html')
 | 
			
		||||
    # note that this response will not include a valid CSRF token
 | 
			
		||||
    assert re.search(r'\bcsrfToken: ""', result.content.decode())
 | 
			
		||||
    assert re.search(r'"csrfToken": ""', result.content.decode())
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user