File: nonce.rst

package info (click to toggle)
python-django-csp 3.8-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 300 kB
  • sloc: python: 935; makefile: 135; sh: 6
file content (129 lines) | stat: -rw-r--r-- 3,886 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
==============================
Using the generated CSP nonce
==============================
When ``CSP_INCLUDE_NONCE_IN`` is configured, the nonce value is returned in the CSP headers **if it is used**, e.g. by evaluating the nonce in your template.
To actually make the browser do anything with this value, you will need to include it in the attributes of
the tags that you wish to mark as safe.


.. Note::

   Use view source on a page to see nonce values. **Nonce values are
   not visible in browser developer tools.** To prevent malicious CSS
   selectors leaking the values, `they are not exposed to the DOM
   <https://github.com/whatwg/html/pull/2373>`_.


``Middleware``
==============
Installing the middleware creates a lazily evaluated property ``csp_nonce`` and attaches it to all incoming requests.

.. code-block:: python

    MIDDLEWARE = (
    	#...
    	'csp.middleware.CSPMiddleware',
    	#...
    )

This value can be accessed directly on the request object in any view or template and manually appended to any script element like so -

.. code-block:: html

	<script nonce="{{request.csp_nonce}}">
		var hello="world";
	</script>

Assuming the ``CSP_INCLUDE_NONCE_IN`` list contains the ``script-src`` directive, this will result in the above script being allowed.

.. Note::

   The nonce will only be added to the CSP headers if it is used.


``Context Processor``
=====================
This library contains an optional context processor, adding ``csp.context_processors.nonce`` to your configured context processors exposes a variable called ``CSP_NONCE`` into the global template context. This is simple shorthand for ``request.csp_nonce``, but can be useful if you have many occurrences of script tags.

.. code-block:: jinja

    <script nonce="{{CSP_NONCE}}">
    	var hello="world";
    </script>


``Django Template Tag/Jinja Extension``
=======================================

.. note::

   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.


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.

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.


Django Templates
----------------

Add the CSP template tags to the TEMPLATES section of your settings file:

.. code-block:: python

	TEMPLATES = [
	    {
		"OPTIONS": {
		    'libraries':          {
			'csp': 'csp.templatetags.csp',
		    }
		},
	    }
	]

Then load the ``csp`` template tags and use ``script`` in the template:

.. code-block:: jinja

	{% load csp %}
	{% script type="application/javascript" async=False %}
		<script>
			var hello='world';
		</script>
	{% endscript %}


Jinja
-----

Add ``csp.extensions.NoncedScript`` to the TEMPLATES section of your settings file:

.. code-block:: python

          TEMPLATES = [
              {
                  'BACKEND':'django.template.backends.jinja2.Jinja2',
                  'OPTIONS': {
                      'extensions': [
                          'csp.extensions.NoncedScript',
                      ],
                  }
             }
          ]


.. code-block:: jinja

	{% script type="application/javascript" async=False %}
		<script>
			var hello='world';
		</script>
	{% endscript %}


Both templates output the following with a different nonce:

.. code-block:: html

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