Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.10/site-packages/django/core/checks/security/base.py: 53%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

104 statements  

1from django.conf import settings 

2from django.core.exceptions import ImproperlyConfigured 

3 

4from .. import Error, Tags, Warning, register 

5 

6CROSS_ORIGIN_OPENER_POLICY_VALUES = { 

7 "same-origin", 

8 "same-origin-allow-popups", 

9 "unsafe-none", 

10} 

11REFERRER_POLICY_VALUES = { 

12 "no-referrer", 

13 "no-referrer-when-downgrade", 

14 "origin", 

15 "origin-when-cross-origin", 

16 "same-origin", 

17 "strict-origin", 

18 "strict-origin-when-cross-origin", 

19 "unsafe-url", 

20} 

21 

22SECRET_KEY_INSECURE_PREFIX = "django-insecure-" 

23SECRET_KEY_MIN_LENGTH = 50 

24SECRET_KEY_MIN_UNIQUE_CHARACTERS = 5 

25 

26SECRET_KEY_WARNING_MSG = ( 

27 f"Your %s has less than {SECRET_KEY_MIN_LENGTH} characters, less than " 

28 f"{SECRET_KEY_MIN_UNIQUE_CHARACTERS} unique characters, or it's prefixed " 

29 f"with '{SECRET_KEY_INSECURE_PREFIX}' indicating that it was generated " 

30 f"automatically by Django. Please generate a long and random value, " 

31 f"otherwise many of Django's security-critical features will be " 

32 f"vulnerable to attack." 

33) 

34 

35W001 = Warning( 

36 "You do not have 'django.middleware.security.SecurityMiddleware' " 

37 "in your MIDDLEWARE so the SECURE_HSTS_SECONDS, " 

38 "SECURE_CONTENT_TYPE_NOSNIFF, SECURE_REFERRER_POLICY, " 

39 "SECURE_CROSS_ORIGIN_OPENER_POLICY, and SECURE_SSL_REDIRECT settings will " 

40 "have no effect.", 

41 id="security.W001", 

42) 

43 

44W002 = Warning( 

45 "You do not have " 

46 "'django.middleware.clickjacking.XFrameOptionsMiddleware' in your " 

47 "MIDDLEWARE, so your pages will not be served with an " 

48 "'x-frame-options' header. Unless there is a good reason for your " 

49 "site to be served in a frame, you should consider enabling this " 

50 "header to help prevent clickjacking attacks.", 

51 id="security.W002", 

52) 

53 

54W004 = Warning( 

55 "You have not set a value for the SECURE_HSTS_SECONDS setting. " 

56 "If your entire site is served only over SSL, you may want to consider " 

57 "setting a value and enabling HTTP Strict Transport Security. " 

58 "Be sure to read the documentation first; enabling HSTS carelessly " 

59 "can cause serious, irreversible problems.", 

60 id="security.W004", 

61) 

62 

63W005 = Warning( 

64 "You have not set the SECURE_HSTS_INCLUDE_SUBDOMAINS setting to True. " 

65 "Without this, your site is potentially vulnerable to attack " 

66 "via an insecure connection to a subdomain. Only set this to True if " 

67 "you are certain that all subdomains of your domain should be served " 

68 "exclusively via SSL.", 

69 id="security.W005", 

70) 

71 

72W006 = Warning( 

73 "Your SECURE_CONTENT_TYPE_NOSNIFF setting is not set to True, " 

74 "so your pages will not be served with an " 

75 "'X-Content-Type-Options: nosniff' header. " 

76 "You should consider enabling this header to prevent the " 

77 "browser from identifying content types incorrectly.", 

78 id="security.W006", 

79) 

80 

81W008 = Warning( 

82 "Your SECURE_SSL_REDIRECT setting is not set to True. " 

83 "Unless your site should be available over both SSL and non-SSL " 

84 "connections, you may want to either set this setting True " 

85 "or configure a load balancer or reverse-proxy server " 

86 "to redirect all connections to HTTPS.", 

87 id="security.W008", 

88) 

89 

90W009 = Warning( 

91 SECRET_KEY_WARNING_MSG % "SECRET_KEY", 

92 id="security.W009", 

93) 

94 

95W018 = Warning( 

96 "You should not have DEBUG set to True in deployment.", 

97 id="security.W018", 

98) 

99 

100W019 = Warning( 

101 "You have " 

102 "'django.middleware.clickjacking.XFrameOptionsMiddleware' in your " 

103 "MIDDLEWARE, but X_FRAME_OPTIONS is not set to 'DENY'. " 

104 "Unless there is a good reason for your site to serve other parts of " 

105 "itself in a frame, you should change it to 'DENY'.", 

106 id="security.W019", 

107) 

108 

109W020 = Warning( 

110 "ALLOWED_HOSTS must not be empty in deployment.", 

111 id="security.W020", 

112) 

113 

114W021 = Warning( 

115 "You have not set the SECURE_HSTS_PRELOAD setting to True. Without this, " 

116 "your site cannot be submitted to the browser preload list.", 

117 id="security.W021", 

118) 

119 

120W022 = Warning( 

121 "You have not set the SECURE_REFERRER_POLICY setting. Without this, your " 

122 "site will not send a Referrer-Policy header. You should consider " 

123 "enabling this header to protect user privacy.", 

124 id="security.W022", 

125) 

126 

127E023 = Error( 

128 "You have set the SECURE_REFERRER_POLICY setting to an invalid value.", 

129 hint="Valid values are: {}.".format(", ".join(sorted(REFERRER_POLICY_VALUES))), 

130 id="security.E023", 

131) 

132 

133E024 = Error( 

134 "You have set the SECURE_CROSS_ORIGIN_OPENER_POLICY setting to an invalid " 

135 "value.", 

136 hint="Valid values are: {}.".format( 

137 ", ".join(sorted(CROSS_ORIGIN_OPENER_POLICY_VALUES)), 

138 ), 

139 id="security.E024", 

140) 

141 

142W025 = Warning(SECRET_KEY_WARNING_MSG, id="security.W025") 

143 

144 

145def _security_middleware(): 

146 return "django.middleware.security.SecurityMiddleware" in settings.MIDDLEWARE 

147 

148 

149def _xframe_middleware(): 

150 return ( 

151 "django.middleware.clickjacking.XFrameOptionsMiddleware" in settings.MIDDLEWARE 

152 ) 

153 

154 

155@register(Tags.security, deploy=True) 

156def check_security_middleware(app_configs, **kwargs): 

157 passed_check = _security_middleware() 

158 return [] if passed_check else [W001] 

159 

160 

161@register(Tags.security, deploy=True) 

162def check_xframe_options_middleware(app_configs, **kwargs): 

163 passed_check = _xframe_middleware() 

164 return [] if passed_check else [W002] 

165 

166 

167@register(Tags.security, deploy=True) 

168def check_sts(app_configs, **kwargs): 

169 passed_check = not _security_middleware() or settings.SECURE_HSTS_SECONDS 

170 return [] if passed_check else [W004] 

171 

172 

173@register(Tags.security, deploy=True) 

174def check_sts_include_subdomains(app_configs, **kwargs): 

175 passed_check = ( 

176 not _security_middleware() 

177 or not settings.SECURE_HSTS_SECONDS 

178 or settings.SECURE_HSTS_INCLUDE_SUBDOMAINS is True 

179 ) 

180 return [] if passed_check else [W005] 

181 

182 

183@register(Tags.security, deploy=True) 

184def check_sts_preload(app_configs, **kwargs): 

185 passed_check = ( 

186 not _security_middleware() 

187 or not settings.SECURE_HSTS_SECONDS 

188 or settings.SECURE_HSTS_PRELOAD is True 

189 ) 

190 return [] if passed_check else [W021] 

191 

192 

193@register(Tags.security, deploy=True) 

194def check_content_type_nosniff(app_configs, **kwargs): 

195 passed_check = ( 

196 not _security_middleware() or settings.SECURE_CONTENT_TYPE_NOSNIFF is True 

197 ) 

198 return [] if passed_check else [W006] 

199 

200 

201@register(Tags.security, deploy=True) 

202def check_ssl_redirect(app_configs, **kwargs): 

203 passed_check = not _security_middleware() or settings.SECURE_SSL_REDIRECT is True 

204 return [] if passed_check else [W008] 

205 

206 

207def _check_secret_key(secret_key): 

208 return ( 

209 len(set(secret_key)) >= SECRET_KEY_MIN_UNIQUE_CHARACTERS 

210 and len(secret_key) >= SECRET_KEY_MIN_LENGTH 

211 and not secret_key.startswith(SECRET_KEY_INSECURE_PREFIX) 

212 ) 

213 

214 

215@register(Tags.security, deploy=True) 

216def check_secret_key(app_configs, **kwargs): 

217 try: 

218 secret_key = settings.SECRET_KEY 

219 except (ImproperlyConfigured, AttributeError): 

220 passed_check = False 

221 else: 

222 passed_check = _check_secret_key(secret_key) 

223 return [] if passed_check else [W009] 

224 

225 

226@register(Tags.security, deploy=True) 

227def check_secret_key_fallbacks(app_configs, **kwargs): 

228 warnings = [] 

229 try: 

230 fallbacks = settings.SECRET_KEY_FALLBACKS 

231 except (ImproperlyConfigured, AttributeError): 

232 warnings.append(Warning(W025.msg % "SECRET_KEY_FALLBACKS", id=W025.id)) 

233 else: 

234 for index, key in enumerate(fallbacks): 

235 if not _check_secret_key(key): 

236 warnings.append( 

237 Warning(W025.msg % f"SECRET_KEY_FALLBACKS[{index}]", id=W025.id) 

238 ) 

239 return warnings 

240 

241 

242@register(Tags.security, deploy=True) 

243def check_debug(app_configs, **kwargs): 

244 passed_check = not settings.DEBUG 

245 return [] if passed_check else [W018] 

246 

247 

248@register(Tags.security, deploy=True) 

249def check_xframe_deny(app_configs, **kwargs): 

250 passed_check = not _xframe_middleware() or settings.X_FRAME_OPTIONS == "DENY" 

251 return [] if passed_check else [W019] 

252 

253 

254@register(Tags.security, deploy=True) 

255def check_allowed_hosts(app_configs, **kwargs): 

256 return [] if settings.ALLOWED_HOSTS else [W020] 

257 

258 

259@register(Tags.security, deploy=True) 

260def check_referrer_policy(app_configs, **kwargs): 

261 if _security_middleware(): 

262 if settings.SECURE_REFERRER_POLICY is None: 

263 return [W022] 

264 # Support a comma-separated string or iterable of values to allow fallback. 

265 if isinstance(settings.SECURE_REFERRER_POLICY, str): 

266 values = {v.strip() for v in settings.SECURE_REFERRER_POLICY.split(",")} 

267 else: 

268 values = set(settings.SECURE_REFERRER_POLICY) 

269 if not values <= REFERRER_POLICY_VALUES: 

270 return [E023] 

271 return [] 

272 

273 

274@register(Tags.security, deploy=True) 

275def check_cross_origin_opener_policy(app_configs, **kwargs): 

276 if ( 

277 _security_middleware() 

278 and settings.SECURE_CROSS_ORIGIN_OPENER_POLICY is not None 

279 and settings.SECURE_CROSS_ORIGIN_OPENER_POLICY 

280 not in CROSS_ORIGIN_OPENER_POLICY_VALUES 

281 ): 

282 return [E024] 

283 return []