| --- |
| title: Security Configurations |
| sidebar_position: 1 |
| --- |
| |
| Authentication and authorization in Superset is handled by Flask AppBuilder (FAB), an application development framework |
| built on top of Flask. FAB provides authentication, user management, permissions and roles. |
| Please read its [Security documentation](https://flask-appbuilder.readthedocs.io/en/latest/security.html). |
| |
| ### Provided Roles |
| |
| Superset ships with a set of roles that are handled by Superset itself. You can assume |
| that these roles will stay up-to-date as Superset evolves (and as you update Superset versions). |
| |
| Even though **Admin** users have the ability, we don't recommend altering the |
| permissions associated with each role (e.g. by removing or adding permissions to them). The permissions |
| associated with each role will be re-synchronized to their original values when you run |
| the **superset init** command (often done between Superset versions). |
| |
| A table with the permissions for these roles can be found at [/RESOURCES/STANDARD_ROLES.md](https://github.com/apache/superset/blob/master/RESOURCES/STANDARD_ROLES.md). |
| |
| ### Admin |
| |
| Admins have all possible rights, including granting or revoking rights from other |
| users and altering other people’s slices and dashboards. |
| |
| >#### Threat Model and Privilege Boundaries: The Admin Role |
| > |
| >Apache Superset is built with a granular permission model where users assigned the Admin role are considered fully trusted. Admins possess complete control over the application's configuration, UI rendering, and access controls. |
| > |
| >Consequently, actions performed by an Admin that alter the application's behavior or presentation—such as injecting custom CSS, modifying Jinja templates, or altering security flags—are intended administrative capabilities by design. |
| > |
| >In accordance with MITRE CNA Rule 4.1, a vulnerability must represent a violation of an explicit security policy. Because the Admin role is defined as a trusted operational boundary, actions executed with Admin privileges do not cross a security perimeter. Therefore, exploit vectors that strictly require Admin access are not classified as security vulnerabilities and are ineligible for CVE assignment. |
| |
| ### Alpha |
| |
| Alpha users have access to all data sources, but they cannot grant or revoke access |
| from other users. They are also limited to altering the objects that they own. Alpha users can add and alter data sources. |
| |
| ### Gamma |
| |
| Gamma users have limited access. They can only consume data coming from data sources |
| they have been given access to through another complementary role. They only have access to |
| view the slices and dashboards made from data sources that they have access to. Currently Gamma |
| users are not able to alter or add data sources. We assume that they are mostly content consumers, though they can create slices and dashboards. |
| |
| Also note that when Gamma users look at the dashboards and slices list view, they will |
| only see the objects that they have access to. |
| |
| ### sql_lab |
| |
| The **sql_lab** role grants access to SQL Lab. Note that while **Admin** users have access |
| to all databases by default, both **Alpha** and **Gamma** users need to be given access on a per database basis. |
| |
| ### Public |
| |
| The **Public** role is the most restrictive built-in role, designed specifically for anonymous/unauthenticated |
| users who need to view dashboards. It provides minimal read-only access for: |
| |
| - Viewing dashboards and charts |
| - Using interactive dashboard filters |
| - Accessing dashboard and chart permalinks |
| - Reading embedded dashboards |
| - Viewing annotations on charts |
| |
| The Public role explicitly excludes: |
| - Any write permissions on dashboards, charts, or datasets |
| - SQL Lab access |
| - Share functionality |
| - User profile or admin features |
| - Menu access to most Superset features |
| |
| Anonymous users are automatically assigned the Public role when `AUTH_ROLE_PUBLIC` is configured |
| (a Flask-AppBuilder setting). The `PUBLIC_ROLE_LIKE` setting is **optional** and controls what |
| permissions are synced to the Public role when you run `superset init`: |
| |
| ```python |
| # Optional: Sync sensible default permissions to the Public role |
| PUBLIC_ROLE_LIKE = "Public" |
| |
| # Alternative: Copy permissions from Gamma for broader access |
| # PUBLIC_ROLE_LIKE = "Gamma" |
| ``` |
| |
| If you prefer to manually configure the Public role's permissions (or use `DASHBOARD_RBAC` to |
| grant access at the dashboard level), you do not need to set `PUBLIC_ROLE_LIKE`. |
| |
| **Important notes:** |
| |
| - **Data access is still required:** The Public role only grants UI/API permissions. You must |
| also grant access to specific datasets necessary to view a dashboard. As with other roles, |
| this can be done in two ways: |
| |
| - **Without `DASHBOARD_RBAC`:** Dashboards only appear in the list and are accessible if |
| the user has permission to at least one of their datasets. Grant dataset access by editing |
| the Public role in the Superset UI (Menu → Security → List Roles → Public) and adding the |
| relevant data sources. All published dashboards using those datasets become visible. |
| |
| - **With `DASHBOARD_RBAC` enabled:** Anonymous users will only see dashboards where the |
| "Public" role has been explicitly added in the dashboard's properties. Dataset permissions |
| are not required—DASHBOARD_RBAC handles the cascading permissions check. This provides |
| fine-grained control over which dashboards are publicly visible. |
| |
| - **Role synchronization:** Built-in role permissions (Admin, Alpha, Gamma, sql_lab, and Public |
| when `PUBLIC_ROLE_LIKE = "Public"`) are synchronized when you run `superset init`. Any manual |
| permission edits to these roles may be overwritten during upgrades. To customize the Public |
| role permissions, you can either: |
| - Edit the Public role directly and avoid setting `PUBLIC_ROLE_LIKE` (permissions won't be |
| overwritten by `superset init`) |
| - Copy the Public role via "Copy Role" in the Superset web UI, save it under a different name |
| (e.g., "Public_Custom"), customize the permissions, then update **both** configs: |
| `PUBLIC_ROLE_LIKE = "Public_Custom"` and `AUTH_ROLE_PUBLIC = "Public_Custom"` |
| |
| ### Managing Data Source Access for Gamma Roles |
| |
| Here’s how to provide users access to only specific datasets. First make sure the users with |
| limited access have [only] the Gamma role assigned to them. Second, create a new role (Menu -> Security -> List Roles) and click the + sign. |
| |
| This new window allows you to give this new role a name, attribute it to users and select the |
| tables in the **Permissions** dropdown. To select the data sources you want to associate with this role, simply click on the dropdown and use the typeahead to search for your table names. |
| |
| You can then confirm with users assigned to the **Gamma** role that they see the |
| objects (dashboards and slices) associated with the tables you just extended them. |
| |
| ### Dashboard Access Control |
| |
| Access to dashboards is managed via owners (users that have edit permissions to the dashboard). |
| Non-owner user access can be managed in two ways. Note that dashboards must be published to be |
| visible to other users. |
| |
| #### Dataset-Based Access (Default) |
| |
| By default, users can view published dashboards if they have access to at least one dataset |
| used in that dashboard. Grant dataset access by adding the relevant data source permissions |
| to a role (Menu → Security → List Roles). |
| |
| This is the simplest approach but provides all-or-nothing access based on dataset permissions— |
| if a user has access to a dataset, they can see all published dashboards using that dataset. |
| |
| #### Dashboard-Level Access (DASHBOARD_RBAC) |
| |
| For fine-grained control over which dashboards specific roles can access, enable the |
| `DASHBOARD_RBAC` feature flag: |
| |
| ```python |
| FEATURE_FLAGS = { |
| "DASHBOARD_RBAC": True, |
| } |
| ``` |
| |
| With this enabled, you can assign specific roles to each dashboard in its properties. Users |
| will only see dashboards where their role is explicitly added. |
| |
| **Important considerations:** |
| - Dashboard access **bypasses** dataset-level checks—granting a role access to a dashboard |
| implicitly grants read access to all charts and datasets in that dashboard |
| - Dashboards without any assigned roles fall back to dataset-based access |
| - The dashboard must still be published to be visible |
| |
| This feature is particularly useful for: |
| - Making specific dashboards public while keeping others private |
| - Granting access to dashboards without exposing the underlying datasets for other uses |
| - Creating dashboard-specific access patterns that don't align with dataset ownership |
| |
| ### SQL Execution Security Considerations |
| |
| Apache Superset includes features designed to provide safeguards when interacting with connected databases, such as the `DISALLOWED_SQL_FUNCTIONS` configuration setting. This aims to prevent the execution of potentially harmful database functions or system variables directly from Superset interfaces like SQL Lab. |
| |
| However, it is crucial to understand the following: |
| |
| **Superset is Not a Database Firewall**: Superset's built-in checks, like `DISALLOWED_SQL_FUNCTIONS`, provide a layer of protection but cannot guarantee complete security against all database-level threats or advanced bypass techniques (like specific comment injection methods). They should be viewed as a supplement to, not a replacement for, robust database security. |
| |
| **Configuration is Key**: The effectiveness of Superset's safeguards heavily depends on proper configuration by the Superset administrator. This includes maintaining the `DISALLOWED_SQL_FUNCTIONS` list, carefully managing feature flags (like `ENABLE_TEMPLATE_PROCESSING`), and configuring other security settings appropriately. |
| |
| **Database Security is Paramount**: The ultimate responsibility for securing database access, controlling permissions, and preventing unauthorized function execution lies with the database administrators (DBAs) and security teams managing the underlying database instance. |
| |
| **Recommended Database Practices**: We strongly recommend implementing security best practices at the database level, including: |
| * **Least Privilege**: Connecting Superset using dedicated database user accounts with the minimum permissions required for Superset's operation (typically read-only access to necessary schemas/tables). |
| * **Database Roles & Permissions**: Utilizing database-native roles and permissions to restrict access to sensitive functions, system variables (like `@@hostname`), schemas, or tables. |
| * **Network Security**: Employing network-level controls like database firewalls or proxies to restrict connections. |
| * **Auditing**: Enabling database-level auditing to monitor executed queries and access patterns. |
| |
| By combining Superset's configurable safeguards with strong database-level security practices, you can achieve a more robust and layered security posture. |
| |
| ### REST API for user & role management |
| |
| Flask-AppBuilder supports a REST API for user CRUD, |
| but this feature is in beta and is not enabled by default in Superset. |
| To enable this feature, set the following in your Superset configuration: |
| |
| ```python |
| FAB_ADD_SECURITY_API = True |
| ``` |
| |
| Once configured, the documentation for additional "Security" endpoints will be visible in Swagger for you to explore. |
| |
| ### Customizing Permissions |
| |
| The permissions exposed by FAB are very granular and allow for a great level of |
| customization. FAB creates many permissions automatically for each model that is |
| created (can_add, can_delete, can_show, can_edit, …) as well as for each view. |
| On top of that, Superset can expose more granular permissions like **all_datasource_access**. |
| |
| **We do not recommend altering the 3 base roles as there are a set of assumptions that |
| Superset is built upon**. It is possible though for you to create your own roles, and union them to existing ones. |
| |
| ### Permissions |
| |
| Roles are composed of a set of permissions, and Superset has many categories of |
| permissions. Here are the different categories of permissions: |
| |
| - Model & Action: models are entities like Dashboard, Slice, or User. Each model has |
| a fixed set of permissions, like **can_edit**, **can_show**, **can_delete**, **can_list**, **can_add**, |
| and so on. For example, you can allow a user to delete dashboards by adding **can_delete** on |
| Dashboard entity to a role and granting this user that role. |
| - Views: views are individual web pages, like the Explore view or the SQL Lab view. |
| When granted to a user, they will see that view in its menu items, and be able to load that page. |
| - Data source: For each data source, a permission is created. If the user does not have the |
| `all_datasource_access permission` granted, the user will only be able to see Slices or explore the data sources that are granted to them |
| - Database: Granting access to a database allows for the user to access all |
| data sources within that database, and will enable the user to query that |
| database in SQL Lab, provided that the SQL Lab specific permission have been granted to the user |
| |
| ### Restricting Access to a Subset of Data Sources |
| |
| We recommend giving a user the **Gamma** role plus any other roles that would add |
| access to specific data sources. We recommend that you create individual roles for |
| each access profile. For example, the users on the Finance team might have access to a set of |
| databases and data sources; these permissions can be consolidated in a single role. |
| Users with this profile then need to be assigned the **Gamma** role as a foundation to |
| the models and views they can access, and that Finance role that is a collection of permissions to data objects. |
| |
| A user can have multiple roles associated with them. For example, an executive on the Finance |
| team could be granted **Gamma**, **Finance**, and the **Executive** roles. The **Executive** |
| role could provide access to a set of data sources and dashboards made available only to executives. |
| In the **Dashboards** view, a user can only see the ones they have access to |
| based on the roles and permissions that were attributed. |
| |
| ### Row Level Security |
| |
| Using Row Level Security filters (under the **Security** menu) you can create filters |
| that are assigned to a particular table, as well as a set of roles. |
| If you want members of the Finance team to only have access to |
| rows where `department = "finance"`, you could: |
| |
| - Create a Row Level Security filter with that clause (`department = "finance"`) |
| - Then assign the clause to the **Finance** role and the table it applies to |
| |
| The **clause** field, which can contain arbitrary text, is then added to the generated |
| SQL statement’s WHERE clause. So you could even do something like create a filter |
| for the last 30 days and apply it to a specific role, with a clause |
| like `date_field > DATE_SUB(NOW(), INTERVAL 30 DAY)`. It can also support |
| multiple conditions: `client_id = 6` AND `advertiser="foo"`, etc. |
| |
| All relevant Row level security filters will be combined together (under the hood, |
| the different SQL clauses are combined using AND statements). This means it's |
| possible to create a situation where two roles conflict in such a way as to limit a table subset to empty. |
| |
| 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. |
| |
| ### 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. |
| |
| #### Switching to server side sessions |
| |
| Server side sessions offer benefits over client side sessions on security and performance. |
| By enabling server side sessions, the session data is stored server side and only a session ID |
| is sent to the client. When a user logs in, a session is created server side and the session ID |
| is sent to the client in a cookie. The client will send the session ID with each request and the |
| server will use it to retrieve the session data. |
| On logout, the session is destroyed server side and the session cookie is deleted on the client side. |
| This reduces the risk for replay attacks and session hijacking. |
| |
| Superset uses [Flask-Session](https://flask-session.readthedocs.io/en/latest/) to manage server side sessions. |
| To enable this extension you have to set: |
| |
| ``` python |
| SESSION_SERVER_SIDE = True |
| ``` |
| |
| Flask-Session offers multiple backend session interfaces for Flask, here's an example for Redis: |
| |
| ``` python |
| from redis import Redis |
| |
| SESSION_TYPE = "redis" |
| SESSION_REDIS = Redis(host="redis", port=6379, db=0) |
| # sign the session cookie sid |
| SESSION_USE_SIGNER = True |
| ``` |
| |
| ### Content Security Policy (CSP) |
| |
| Superset uses the [Talisman](https://pypi.org/project/flask-talisman/) extension to enable implementation of a |
| [Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP), an added |
| layer of security that helps to detect and mitigate certain types of attacks, including |
| Cross-Site Scripting (XSS) and data injection attacks. |
| |
| A 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 correctly configure a Content Security Policy when deploying Superset to |
| prevent many types of attacks. Superset provides two variables in `config.py` for deploying a CSP: |
| |
| - `TALISMAN_ENABLED` defaults to `True`; set this to `False` in order to disable CSP |
| - `TALISMAN_CONFIG` holds the actual the policy definition (*see example below*) as well as any |
| other arguments to be passed to Talisman. |
| |
| When running in production mode, Superset will check at startup for the presence |
| of a CSP. If one is not found, 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 |
| this warning using the `CONTENT_SECURITY_POLICY_WARNING` key in `config.py`. |
| |
| #### CSP Requirements |
| |
| - Superset needs the `style-src unsafe-inline` CSP directive in order to operate. |
| |
| ``` |
| style-src 'self' 'unsafe-inline' |
| ``` |
| |
| - Only scripts marked with a [nonce](https://content-security-policy.com/nonce/) can be loaded and executed. |
| Nonce is a random string automatically generated by Talisman on each page load. |
| You can get current nonce value by calling jinja macro `csp_nonce()`. |
| |
| ```html |
| <script nonce="{{ csp_nonce() }}"> |
| /* my script */ |
| </script> |
| ``` |
| |
| - Some dashboards load images using data URIs and require `data:` in their `img-src` |
| |
| ``` |
| img-src 'self' data: |
| ``` |
| |
| - MapBox charts use workers and need to connect to MapBox servers in addition to the Superset origin |
| |
| ``` |
| worker-src 'self' blob: |
| connect-src 'self' https://api.mapbox.com https://events.mapbox.com |
| ``` |
| |
| - Cartodiagram charts request map data (image and json) from external resources that can be edited by users, |
| and therefore either require a list of allowed domains to request from or a wildcard (`'*'`) for `img-src` and `connect-src`. |
| |
| - Other CSP directives default to `'self'` to limit content to the same origin as the Superset server. |
| |
| In order to adjust provided CSP configuration to your needs, follow the instructions and examples provided in |
| [Content Security Policy Reference](https://content-security-policy.com/) |
| |
| #### Other Talisman security considerations |
| |
| Setting `TALISMAN_ENABLED = True` will invoke Talisman's protection with its default arguments, |
| of which `content_security_policy` is only one. Those can be found in the |
| [Talisman documentation](https://pypi.org/project/flask-talisman/) under *Options*. |
| These generally improve security, but administrators should be aware of their existence. |
| |
| In particular, the option of `force_https = True` (`False` by default) may break Superset's Alerts & Reports |
| if workers are configured to access charts via a `WEBDRIVER_BASEURL` beginning |
| with `http://`. As long as a Superset deployment enforces https upstream, e.g., |
| through a load balancer or application gateway, it should be acceptable to keep this |
| option disabled. Otherwise, you may want to enable `force_https` like this: |
| |
| ```python |
| TALISMAN_CONFIG = { |
| "force_https": True, |
| "content_security_policy": { ... |
| ``` |
| |
| #### Configuring Talisman in Superset |
| |
| Talisman settings in Superset can be modified using superset_config.py. If you need to adjust security policies, you can override the default configuration. |
| |
| Example: Overriding Talisman Configuration in superset_config.py for loading images form s3 or other external sources. |
| |
| ```python |
| TALISMAN_CONFIG = { |
| "content_security_policy": { |
| "base-uri": ["'self'"], |
| "default-src": ["'self'"], |
| "img-src": [ |
| "'self'", |
| "blob:", |
| "data:", |
| "https://apachesuperset.gateway.scarf.sh", |
| "https://static.scarf.sh/", |
| # "https://cdn.brandfolder.io", # Uncomment when SLACK_ENABLE_AVATARS is True # noqa: E501 |
| "ows.terrestris.de", |
| "aws.s3.com", # Add Your Bucket or external data source |
| ], |
| "worker-src": ["'self'", "blob:"], |
| "connect-src": [ |
| "'self'", |
| "https://api.mapbox.com", |
| "https://events.mapbox.com", |
| ], |
| "object-src": "'none'", |
| "style-src": [ |
| "'self'", |
| "'unsafe-inline'", |
| ], |
| "script-src": ["'self'", "'strict-dynamic'"], |
| }, |
| "content_security_policy_nonce_in": ["script-src"], |
| "force_https": False, |
| "session_cookie_secure": False, |
| } |
| ``` |
| |
| For more information on setting up Talisman, please refer to |
| https://superset.apache.org/admin-docs/configuration/networking-settings/#changing-flask-talisman-csp. |
| |
| ### Reporting Security Vulnerabilities |
| |
| Apache Software Foundation takes a rigorous standpoint in annihilating the security issues in its |
| software projects. Apache Superset is highly sensitive and forthcoming to issues pertaining to its |
| features and functionality. |
| |
| If you have apprehensions regarding Superset security or you discover vulnerability or potential |
| threat, don’t hesitate to get in touch with the Apache Security Team by dropping a mail at |
| security@apache.org. In the mail, specify the project name Superset with the description of the |
| issue or potential threat. You are also urged to recommend the way to reproduce and replicate the |
| issue. The security team and the Superset community will get back to you after assessing and |
| analysing the findings. |
| |
| PLEASE PAY ATTENTION to report the security issue on the security email before disclosing it on |
| public domain. The ASF Security Team maintains a page with the description of how vulnerabilities |
| and potential threats are handled, check [their web page](https://apache.org/security/committers.html) |
| for more details. |