mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-01-21 07:55:00 +00:00
middleware: Implement middleware for common headers such as CSP
- This allows overriding these headers in individual pages easily instead of relaxing global policy. - Drop the obsolete CSP directive "block-all-mixed-content" and avoid a console warning in Firefox. Tests: - Load a page and notice in the browser developer tools that the three headers referrer-policy, content-security-policy, and x-content-type-options are set as before. Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org> Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
parent
3eef1d9324
commit
2467d6a033
@ -47,48 +47,6 @@
|
||||
RedirectMatch "^/$" "/plinth"
|
||||
</IfFile>
|
||||
|
||||
##
|
||||
## Disable sending Referer (sic) header from FreedomBox web interface to
|
||||
## external websites. This improves privacy by not disclosing FreedomBox
|
||||
## domains/URLs to external domains. Apps such as blogs which want to popularize
|
||||
## themselves with referrer header may still do so.
|
||||
##
|
||||
## A strict Content Security Policy.
|
||||
## - @fonts are allowed only from FreedomBox itself.
|
||||
## - <frame>/<iframe> sources are disabled.
|
||||
## - <img> sources are allowed only from FreedomBox itself.
|
||||
## - Manifest file is not allowed as there is none yet.
|
||||
## - <audio>, <video>, <track> tags are not allowed yet.
|
||||
## - <object>, <embed>, <applet> tags are not allowed yet.
|
||||
## - Allow JS from FreedomBox itself (no inline and attribute scripts).
|
||||
## - Allow inline CSS and CSS files from Freedombox itself.
|
||||
## - Web worker sources are allowed only from FreedomBox itself (for JSXC).
|
||||
## - All other fetch sources including Ajax are not allowed from FreedomBox
|
||||
## itself.
|
||||
## - <base> tag is not allowed.
|
||||
## - No plugins types are alllowed since object-src is 'none'.
|
||||
## - Form action should be to FreedomBox itself.
|
||||
## - This interface may be not embedded in <frame>, <iframe>, etc. tags.
|
||||
## - When serving HTTPS, don't allow HTTP assets.
|
||||
##
|
||||
## Enable strict sandboxing enabled with some exceptions:
|
||||
## - Allow running Javascript.
|
||||
## - Allow popups as sometimes we use <a target=_blank>
|
||||
## - Allow popups to have different sandbox requirements as we launch apps' web
|
||||
## clients.
|
||||
## - Allow forms to support configuration forms.
|
||||
## - Allow policies to treat same origin differently from other origins
|
||||
## - Allow downloads such as backup tarballs.
|
||||
##
|
||||
## Disable browser guessing of MIME types. FreedoBox already sets good content
|
||||
## types for all the common file types.
|
||||
##
|
||||
<LocationMatch "^/(plinth|freedombox)">
|
||||
Header set Referrer-Policy 'same-origin'
|
||||
Header set Content-Security-Policy "font-src 'self'; frame-src 'none'; img-src 'self' data:; manifest-src 'none'; media-src 'none'; object-src 'none'; script-src 'self'; style-src 'self'; worker-src 'self'; default-src 'self'; base-uri 'none'; sandbox allow-scripts allow-popups allow-popups-to-escape-sandbox allow-forms allow-same-origin allow-downloads; form-action 'self'; frame-ancestors 'none'; block-all-mixed-content;"
|
||||
Header set X-Content-Type-Options 'nosniff'
|
||||
</LocationMatch>
|
||||
|
||||
##
|
||||
## On all sites, provide FreedomBox on a default path: /plinth
|
||||
##
|
||||
|
||||
@ -188,3 +188,93 @@ class CommonErrorMiddleware(MiddlewareMixin):
|
||||
breadcrumbs = views.get_breadcrumbs(request)
|
||||
parent_index = 1 if len(breadcrumbs) > 1 else 0
|
||||
return list(breadcrumbs.keys())[parent_index]
|
||||
|
||||
|
||||
class CSPDict(dict):
|
||||
"""A dictionary to store Content Security Policy.
|
||||
|
||||
And return a full value of the HTTP header.
|
||||
"""
|
||||
|
||||
def get_header_value(self) -> str:
|
||||
"""Return the string header value for the policy stored."""
|
||||
return ' '.join([f'{key} {value};' for key, value in self.items()])
|
||||
|
||||
|
||||
CONTENT_SECURITY_POLICY = CSPDict({
|
||||
# @fonts are allowed only from FreedomBox itself.
|
||||
'font-src': "'self'",
|
||||
# <frame>/<iframe> sources are disabled.
|
||||
'frame-src': "'none'",
|
||||
# <img> sources are allowed only from FreedomBox itself. Allow
|
||||
# data: URLs for SVGs in CSS.
|
||||
'img-src': "'self' data:",
|
||||
# Manifest file is not allowed as there is none yet.
|
||||
'manifest-src': "'none'",
|
||||
# <audio>, <video>, <track> tags are not allowed yet.
|
||||
'media-src': "'none'",
|
||||
# <object>, <embed>, <applet> tags are not allowed yet. No plugins
|
||||
# types are alllowed since object-src is 'none'.
|
||||
'object-src': "'none'",
|
||||
# Allow JS from FreedomBox itself (no inline and attribute
|
||||
# scripts).
|
||||
'script-src': "'self'",
|
||||
# Allow inline CSS and CSS files from Freedombox itself.
|
||||
'style-src': "'self'",
|
||||
# Web worker sources are allowed only from FreedomBox itself (for
|
||||
# JSXC).
|
||||
'worker-src': "'self'",
|
||||
# All other fetch sources including Ajax are not allowed from
|
||||
# FreedomBox itself.
|
||||
'default-src': "'self'",
|
||||
# <base> tag is not allowed.
|
||||
'base-uri': "'none'",
|
||||
# Enable strict sandboxing enabled with some exceptions:
|
||||
# - Allow running Javascript.
|
||||
# - Allow popups as sometimes we use <a target=_blank>
|
||||
# - Allow popups to have different sandbox requirements as we
|
||||
# launch apps' web clients.
|
||||
# - Allow forms to support configuration forms.
|
||||
# - Allow policies to treat same origin differently from other
|
||||
# - origins
|
||||
# - Allow downloads such as backup tarballs.
|
||||
'sandbox': 'allow-scripts allow-popups '
|
||||
'allow-popups-to-escape-sandbox allow-forms '
|
||||
'allow-same-origin allow-downloads',
|
||||
# Form action should be to FreedomBox itself.
|
||||
'form-action': "'self'",
|
||||
# This interface may be not embedded in <frame>, <iframe>, etc.
|
||||
# tags.
|
||||
'frame-ancestors': "'none'",
|
||||
})
|
||||
|
||||
|
||||
class CommonHeadersMiddleware:
|
||||
|
||||
def __init__(self, get_response):
|
||||
"""Initialize the middleware object."""
|
||||
self.get_response = get_response
|
||||
|
||||
def __call__(self, request):
|
||||
"""Add common security middleware."""
|
||||
# Disable sending Referer (sic) header from FreedomBox web interface to
|
||||
# external websites. This improves privacy by not disclosing FreedomBox
|
||||
# domains/URLs to external domains. Apps such as blogs which want to
|
||||
# popularize themselves with referrer header may still do so.
|
||||
response = self.get_response(request)
|
||||
if not response.get('Referrer-Policy'):
|
||||
response['Referrer-Policy'] = 'same-origin'
|
||||
|
||||
# Disable browser guessing of MIME types. FreedoBox already sets good
|
||||
# content types for all the common file types.
|
||||
if not response.get('X-Content-Type-Options'):
|
||||
response['X-Content-Type-Options'] = 'nosniff'
|
||||
|
||||
csp = ' '.join([
|
||||
f'{key} {value};'
|
||||
for key, value in CONTENT_SECURITY_POLICY.items()
|
||||
])
|
||||
if not response.get('Content-Security-Policy'):
|
||||
response['Content-Security-Policy'] = csp
|
||||
|
||||
return response
|
||||
|
||||
@ -149,6 +149,7 @@ LOGIN_REDIRECT_URL = 'index'
|
||||
MESSAGE_TAGS: dict = {}
|
||||
|
||||
MIDDLEWARE = (
|
||||
'plinth.middleware.CommonHeadersMiddleware',
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'django.middleware.locale.LocaleMiddleware',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user