Support sending a custom Content-Security-Policy header in Website mode

This commit is contained in:
Micah Lee 2021-11-23 18:44:14 -08:00
commit a4985e7029
No known key found for this signature in database
GPG key ID: 403C2657CD994F73
6 changed files with 103 additions and 10 deletions

View file

@ -150,7 +150,13 @@ def main(cwd=None):
action="store_true",
dest="disable_csp",
default=False,
help="Publish website: Disable Content Security Policy header (allows your website to use third-party resources)",
help="Publish website: Disable the default Content Security Policy header (allows your website to use third-party resources)",
)
parser.add_argument(
"--custom_csp",
metavar="custom_csp",
default=None,
help="Publish website: Set a custom Content Security Policy header",
)
# Other
parser.add_argument(
@ -189,6 +195,7 @@ def main(cwd=None):
disable_text = args.disable_text
disable_files = args.disable_files
disable_csp = bool(args.disable_csp)
custom_csp = args.custom_csp
verbose = bool(args.verbose)
# Verbose mode?
@ -234,7 +241,15 @@ def main(cwd=None):
mode_settings.set("receive", "disable_text", disable_text)
mode_settings.set("receive", "disable_files", disable_files)
if mode == "website":
mode_settings.set("website", "disable_csp", disable_csp)
if disable_csp and custom_csp:
print("You cannot disable the CSP and set a custom one. Either set --disable-csp or --custom-csp but not both.")
sys.exit()
if disable_csp:
mode_settings.set("website", "disable_csp", True)
mode_settings.set("website", "custom_csp", None)
if custom_csp:
mode_settings.set("website", "custom_csp", custom_csp)
mode_settings.set("website", "disable_csp", False)
else:
# See what the persistent mode was
mode = mode_settings.get("persistent", "mode")

View file

@ -55,7 +55,11 @@ class ModeSettings:
"disable_text": False,
"disable_files": False,
},
"website": {"disable_csp": False, "filenames": []},
"website": {
"disable_csp": False,
"custom_csp": None,
"filenames": []
},
"chat": {"room": "default"},
}
self._settings = {}

View file

@ -199,11 +199,18 @@ class Web:
for header, value in self.security_headers:
r.headers.set(header, value)
# Set a CSP header unless in website mode and the user has disabled it
if not self.settings.get("website", "disable_csp") or self.mode != "website":
default_csp = "default-src 'self'; frame-ancestors 'none'; form-action 'self'; base-uri 'self'; img-src 'self' data:;"
if self.mode != "website" or (not self.settings.get("website", "disable_csp") and not self.settings.get("website", "custom_csp")):
r.headers.set(
"Content-Security-Policy",
"default-src 'self'; frame-ancestors 'none'; form-action 'self'; base-uri 'self'; img-src 'self' data:;",
default_csp
)
else:
if self.settings.get("website", "custom_csp"):
r.headers.set(
"Content-Security-Policy",
self.settings.get("website", "custom_csp")
)
return r
@self.app.errorhandler(404)