From b156fb67181adf0d98a1b0248bb2c5d8dd3db5d9 Mon Sep 17 00:00:00 2001 From: "Michael S. Molina" Date: Tue, 18 Oct 2022 16:48:44 -0300 Subject: [PATCH 1/3] feat: Adds a Content Security Policy (CSP) check for production environments --- superset/config.py | 7 +++++-- superset/initialization/__init__.py | 22 ++++++++++++++++++++-- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/superset/config.py b/superset/config.py index 64dc3baa125b..c220d1517961 100644 --- a/superset/config.py +++ b/superset/config.py @@ -1223,11 +1223,14 @@ def EMAIL_HEADER_MUTATOR( # pylint: disable=invalid-name,unused-argument # one here. TEST_DATABASE_CONNECTION_TIMEOUT = timedelta(seconds=30) +# Enable/disable CSP warning +CONTENT_SECURITY_POLICY_WARNING = True + # Do you want Talisman enabled? -TALISMAN_ENABLED = False +TALISMAN_ENABLED = True # If you want Talisman, how do you want it configured?? TALISMAN_CONFIG = { - "content_security_policy": None, + "content_security_policy": "default-src 'self'", "force_https": True, "force_https_permanent": False, } diff --git a/superset/initialization/__init__.py b/superset/initialization/__init__.py index 598cf94e055e..4fb18404202c 100644 --- a/superset/initialization/__init__.py +++ b/superset/initialization/__init__.py @@ -575,8 +575,26 @@ def __call__( # Flask-Compress Compress(self.superset_app) - if self.config["TALISMAN_ENABLED"]: - talisman.init_app(self.superset_app, **self.config["TALISMAN_CONFIG"]) + show_csp_warning = False + if ( + self.config["CONTENT_SECURITY_POLICY_WARNING"] + and not self.superset_app.debug + ): + if self.config["TALISMAN_ENABLED"]: + talisman.init_app(self.superset_app, **self.config["TALISMAN_CONFIG"]) + if not self.config["TALISMAN_CONFIG"]["content_security_policy"]: + show_csp_warning = True + else: + show_csp_warning = True + + if show_csp_warning: + logger.warning( + "We haven't found any Content Security Policy (CSP) defined in the configurations. " + "Please make sure to configure CSP using the TALISMAN_CONFIG key or any other external software. " + "Failing to configure CSP have serious security implications. " + "Check https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP for more information. " + "You can disable this warning using the CONTENT_SECURITY_POLICY_WARNING key." + ) def configure_logging(self) -> None: self.config["LOGGING_CONFIGURATOR"].configure_logging( From 357db142a62c560cca6c0696f87ad3308723af79 Mon Sep 17 00:00:00 2001 From: "Michael S. Molina" Date: Wed, 19 Oct 2022 13:26:38 -0300 Subject: [PATCH 2/3] Fix config.py --- superset/config.py | 4 ++-- superset/initialization/__init__.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/superset/config.py b/superset/config.py index c220d1517961..66130c9cf9e3 100644 --- a/superset/config.py +++ b/superset/config.py @@ -1227,10 +1227,10 @@ def EMAIL_HEADER_MUTATOR( # pylint: disable=invalid-name,unused-argument CONTENT_SECURITY_POLICY_WARNING = True # Do you want Talisman enabled? -TALISMAN_ENABLED = True +TALISMAN_ENABLED = False # If you want Talisman, how do you want it configured?? TALISMAN_CONFIG = { - "content_security_policy": "default-src 'self'", + "content_security_policy": None, "force_https": True, "force_https_permanent": False, } diff --git a/superset/initialization/__init__.py b/superset/initialization/__init__.py index 4fb18404202c..ed19cdaf5915 100644 --- a/superset/initialization/__init__.py +++ b/superset/initialization/__init__.py @@ -582,7 +582,7 @@ def __call__( ): if self.config["TALISMAN_ENABLED"]: talisman.init_app(self.superset_app, **self.config["TALISMAN_CONFIG"]) - if not self.config["TALISMAN_CONFIG"]["content_security_policy"]: + if not self.config["TALISMAN_CONFIG"].get("content_security_policy"): show_csp_warning = True else: show_csp_warning = True From a9cf42ea6ced665caf877403491c14e42b8392b7 Mon Sep 17 00:00:00 2001 From: "Michael S. Molina" Date: Wed, 19 Oct 2022 18:10:00 -0300 Subject: [PATCH 3/3] Adds CSP docs --- docs/docs/security.mdx | 22 ++++++++++++++++++++++ superset/initialization/__init__.py | 12 +++++++----- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/docs/docs/security.mdx b/docs/docs/security.mdx index 0067f196cb1f..283e48d9b058 100644 --- a/docs/docs/security.mdx +++ b/docs/docs/security.mdx @@ -131,6 +131,28 @@ For example, the filters `client_id=4` and `client_id=5`, applied to a role, will result in users of that role having `client_id=4` AND `client_id=5` added to their query, which can never be true. +### Content Security Policiy (CSP) + +[Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) is an added +layer of security that helps to detect and mitigate certain types of attacks, including +Cross-Site Scripting (XSS) and data injection attacks. + +CSP makes it possible for server administrators to reduce or eliminate the vectors by which XSS can +occur by specifying the domains that the browser should consider to be valid sources of executable scripts. +A CSP compatible browser will then only execute scripts loaded in source files received from those allowed domains, +ignoring all other scripts (including inline scripts and event-handling HTML attributes). + +A policy is described using a series of policy directives, each of which describes the policy for +a certain resource type or policy area. You can check possible directives +[here](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy). + +It's extremely important to correclty configure a Content Security Policy when deploying Superset to +prevent many types of attacks. For that matter, Superset provides the ` TALISMAN_CONFIG` key in `config.py` +where admnistrators can define the policy. When running in production mode, Superset will check for the presence +of a policy and if it's not able to find one, it will issue a warning with the security risks. For environments +where CSP policies are defined outside of Superset using other software, administrators can disable +the warning using the `CONTENT_SECURITY_POLICY_WARNING` key in `config.py`. + ### Reporting Security Vulnerabilities Apache Software Foundation takes a rigorous standpoint in annihilating the security issues in its diff --git a/superset/initialization/__init__.py b/superset/initialization/__init__.py index ed19cdaf5915..65aaeef26eba 100644 --- a/superset/initialization/__init__.py +++ b/superset/initialization/__init__.py @@ -589,11 +589,13 @@ def __call__( if show_csp_warning: logger.warning( - "We haven't found any Content Security Policy (CSP) defined in the configurations. " - "Please make sure to configure CSP using the TALISMAN_CONFIG key or any other external software. " - "Failing to configure CSP have serious security implications. " - "Check https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP for more information. " - "You can disable this warning using the CONTENT_SECURITY_POLICY_WARNING key." + "We haven't found any Content Security Policy (CSP) defined in " + "the configurations. Please make sure to configure CSP using the " + "TALISMAN_CONFIG key or any other external software. Failing to " + "configure CSP have serious security implications. Check " + "https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP for more " + "information. You can disable this warning using the " + "CONTENT_SECURITY_POLICY_WARNING key." ) def configure_logging(self) -> None: