2
2
3
3
import pprint
4
4
from collections .abc import Sequence
5
+ from importlib .metadata import version
5
6
from typing import TYPE_CHECKING , Any
6
7
7
8
from django .conf import settings
8
- from django .core .checks import Error
9
+ from django .core import checks
10
+ from django .core .checks import Error , register
11
+
12
+ from packaging .version import Version
9
13
10
14
from csp .constants import NONCE
11
15
@@ -77,6 +81,7 @@ def migrate_settings() -> tuple[dict[str, Any], bool]:
77
81
return config , REPORT_ONLY
78
82
79
83
84
+ @register (checks .Tags .security )
80
85
def check_django_csp_lt_4_0 (app_configs : Sequence [AppConfig ] | None , ** kwargs : Any ) -> list [Error ]:
81
86
check_settings = OUTDATED_SETTINGS + ["CSP_REPORT_ONLY" , "CSP_EXCLUDE_URL_PREFIXES" , "CSP_REPORT_PERCENTAGE" ]
82
87
if any (hasattr (settings , setting ) for setting in check_settings ):
@@ -91,3 +96,34 @@ def check_django_csp_lt_4_0(app_configs: Sequence[AppConfig] | None, **kwargs: A
91
96
return [Error (warning , id = "csp.E001" )]
92
97
93
98
return []
99
+
100
+
101
+ @register (checks .Tags .security )
102
+ def check_exclude_url_prefixes_is_not_string (app_configs : Sequence [AppConfig ] | None , ** kwargs : Any ) -> list [Error ]:
103
+ """
104
+ Check that EXCLUDE_URL_PREFIXES in settings is not a string.
105
+
106
+ If it is a string it can lead to a security issue where the string is treated as a list of
107
+ characters, resulting in '/' matching all paths excluding the CSP header from all responses.
108
+
109
+ """
110
+ # Skip check for django-csp < 4.0.
111
+ if Version (version ("django-csp" )) < Version ("4.0a1" ):
112
+ return []
113
+
114
+ errors = []
115
+ keys = (
116
+ "CONTENT_SECURITY_POLICY" ,
117
+ "CONTENT_SECURITY_POLICY_REPORT_ONLY" ,
118
+ )
119
+ for key in keys :
120
+ config = getattr (settings , key , {})
121
+ if isinstance (config , dict ) and isinstance (config .get ("EXCLUDE_URL_PREFIXES" ), str ):
122
+ errors .append (
123
+ Error (
124
+ f"EXCLUDE_URL_PREFIXES in { key } settings must be a list or tuple." ,
125
+ id = "csp.E002" ,
126
+ )
127
+ )
128
+
129
+ return errors
0 commit comments