File: test_middleware.py

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 (140 lines) | stat: -rw-r--r-- 3,953 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
130
131
132
133
134
135
136
137
138
139
140
from django.http import (
    HttpResponse,
    HttpResponseNotFound,
    HttpResponseServerError,
)
from django.test import RequestFactory
from django.test.utils import override_settings

from csp.middleware import CSPMiddleware
from csp.tests.utils import response

HEADER = "Content-Security-Policy"
mw = CSPMiddleware(response())
rf = RequestFactory()


def test_add_header():
    request = rf.get("/")
    response = HttpResponse()
    mw.process_response(request, response)
    assert HEADER in response


def test_exempt():
    request = rf.get("/")
    response = HttpResponse()
    response._csp_exempt = True
    mw.process_response(request, response)
    assert HEADER not in response


@override_settings(CSP_EXCLUDE_URL_PREFIXES=("/inlines-r-us"))
def text_exclude():
    request = rf.get("/inlines-r-us/foo")
    response = HttpResponse()
    mw.process_response(request, response)
    assert HEADER not in response


@override_settings(CSP_REPORT_ONLY=True)
def test_report_only():
    request = rf.get("/")
    response = HttpResponse()
    mw.process_response(request, response)
    assert HEADER not in response
    assert HEADER + "-Report-Only" in response


def test_dont_replace():
    request = rf.get("/")
    response = HttpResponse()
    response[HEADER] = "default-src example.com"
    mw.process_response(request, response)
    assert response[HEADER] == "default-src example.com"


def test_use_config():
    request = rf.get("/")
    response = HttpResponse()
    response._csp_config = {"default-src": ["example.com"]}
    mw.process_response(request, response)
    assert response[HEADER] == "default-src example.com"


def test_use_update():
    request = rf.get("/")
    response = HttpResponse()
    response._csp_update = {"default-src": ["example.com"]}
    mw.process_response(request, response)
    assert response[HEADER] == "default-src 'self' example.com"


@override_settings(CSP_IMG_SRC=["foo.com"])
def test_use_replace():
    request = rf.get("/")
    response = HttpResponse()
    response._csp_replace = {"img-src": ["bar.com"]}
    mw.process_response(request, response)
    policy_list = sorted(response[HEADER].split("; "))
    assert policy_list == ["default-src 'self'", "img-src bar.com"]


@override_settings(DEBUG=True)
def test_debug_errors_exempt():
    request = rf.get("/")
    response = HttpResponseServerError()
    mw.process_response(request, response)
    assert HEADER not in response


@override_settings(DEBUG=True)
def test_debug_notfound_exempt():
    request = rf.get("/")
    response = HttpResponseNotFound()
    mw.process_response(request, response)
    assert HEADER not in response


def test_nonce_created_when_accessed():
    request = rf.get("/")
    mw.process_request(request)
    nonce = str(request.csp_nonce)
    response = HttpResponse()
    mw.process_response(request, response)
    assert nonce in response[HEADER]


def test_no_nonce_when_not_accessed():
    request = rf.get("/")
    mw.process_request(request)
    response = HttpResponse()
    mw.process_response(request, response)
    assert "nonce-" not in response[HEADER]


def test_nonce_regenerated_on_new_request():
    request1 = rf.get("/")
    request2 = rf.get("/")
    mw.process_request(request1)
    mw.process_request(request2)
    nonce1 = str(request1.csp_nonce)
    nonce2 = str(request2.csp_nonce)
    assert request1.csp_nonce != request2.csp_nonce

    response1 = HttpResponse()
    response2 = HttpResponse()
    mw.process_response(request1, response1)
    mw.process_response(request2, response2)
    assert nonce1 not in response2[HEADER]
    assert nonce2 not in response1[HEADER]


@override_settings(CSP_INCLUDE_NONCE_IN=[])
def test_no_nonce_when_disabled_by_settings():
    request = rf.get("/")
    mw.process_request(request)
    nonce = str(request.csp_nonce)
    response = HttpResponse()
    mw.process_response(request, response)
    assert nonce not in response[HEADER]