From e7e1bdc3458bf8983d4c155500be7a3cd209aebe Mon Sep 17 00:00:00 2001 From: Daniel Vaz Gaspar Date: Thu, 1 Jun 2023 14:01:25 +0100 Subject: [PATCH] fix: enable strong session protection by default (#24256) --- UPDATING.md | 1 + docs/docs/security.mdx | 31 ++++++++++++++++++++++++++++++- superset/config.py | 5 ++++- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/UPDATING.md b/UPDATING.md index f71d884091c64..1b30ec75aea5b 100644 --- a/UPDATING.md +++ b/UPDATING.md @@ -24,6 +24,7 @@ assists people when migrating to a new version. ## 2.1.1 - [24185](https://github.com/apache/superset/pull/24185): `/api/v1/database/test_connection` and `api/v1/database/validate_parameters` permissions changed from `can_read` to `can_write`. Only Admin user's have access. +- [24256](https://github.com/apache/superset/pull/24256): `Flask-Login` session validation is now set to `strong` by default. Previous setting was `basic`. ### Other diff --git a/docs/docs/security.mdx b/docs/docs/security.mdx index e868de6a99aff..eabe17da58711 100644 --- a/docs/docs/security.mdx +++ b/docs/docs/security.mdx @@ -131,7 +131,36 @@ 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) +### User Sessions + +Superset uses [Flask](https://pypi.org/project/Flask/) +and [Flask-Login](https://pypi.org/project/Flask-Login/) for user session management. + +Session cookies are used to maintain session info and user state between requests, +although they do not contain personal user information they serve the purpose of identifying +a user session on the server side. +The session cookie is encrypted with the application `SECRET_KEY` and cannot be read by the client. +So it's very important to keep the `SECRET_KEY` secret and set to a secure unique complex random value. + +Flask and Flask-Login offer a number of configuration options to control session behavior. + +- Relevant Flask settings: + +`SESSION_COOKIE_HTTPONLY`: (default: `False`): Controls if cookies should be set with the `HttpOnly` flag. + +`SESSION_COOKIE_SECURE`: (default: `False`) Browsers will only send cookies with requests over +HTTPS if the cookie is marked “secure”. The application must be served over HTTPS for this to make sense. + +`SESSION_COOKIE_SAMESITE`: (default: "Lax") Prevents the browser from sending this cookie along with cross-site requests. + +`PERMANENT_SESSION_LIFETIME`: (default: "31 days") The lifetime of a permanent session as a `datetime.timedelta` object. + +- Relevant Flask-Login settings: + +`SESSION_PROTECTION`: The method used to protect the session from being stolen. [Documentation](https://flask-login.readthedocs.io/en/latest/#session-protection) +Default: "strong" + +### Content Security Policy (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 diff --git a/superset/config.py b/superset/config.py index f24b040e0f3b0..a48fa191fe7eb 100644 --- a/superset/config.py +++ b/superset/config.py @@ -1205,6 +1205,7 @@ def SQL_QUERY_MUTATOR( # pylint: disable=invalid-name,unused-argument # functionality for both the SQL_Lab and Charts. MUTATE_AFTER_SPLIT = False + # This allows for a user to add header data to any outgoing emails. For example, # if you need to include metadata in the header or you want to change the specifications # of the email title, header, or sender. @@ -1387,6 +1388,8 @@ def EMAIL_HEADER_MUTATOR( # pylint: disable=invalid-name,unused-argument SESSION_COOKIE_HTTPONLY = True # Prevent cookie from being read by frontend JS? SESSION_COOKIE_SECURE = False # Prevent cookie from being transmitted over non-tls? SESSION_COOKIE_SAMESITE: Optional[Literal["None", "Lax", "Strict"]] = "Lax" +# Accepts None, "basic" and "strong", more details on: https://flask-login.readthedocs.io/en/latest/#session-protection +SESSION_PROTECTION = "strong" # Cache static resources. SEND_FILE_MAX_AGE_DEFAULT = int(timedelta(days=365).total_seconds()) @@ -1584,7 +1587,7 @@ class ExtraRelatedQueryFilters(TypedDict, total=False): try: # pylint: disable=import-error,wildcard-import,unused-wildcard-import import superset_config - from superset_config import * # type: ignore + from superset_config import * print(f"Loaded your LOCAL configuration at [{superset_config.__file__}]") except Exception: