korbit-ai[bot] commented on code in PR #35190:
URL: https://github.com/apache/superset/pull/35190#discussion_r2359659866
##########
docs/docs/security/securing_superset.mdx:
##########
@@ -0,0 +1,205 @@
+---
+title: Securing Your Superset Installation for Production
+sidebar_position: 3
+---
+
+> *This guide applies to Apache Superset version 4.0 and later.*
+
+The default Apache Superset configuration is optimized for ease of use and
development, not for security. For any production deployment, it is
**critical** that you review and apply the following security configurations to
harden your instance, protect user data, and prevent unauthorized access.
+
+This guide provides a comprehensive checklist of essential security
configurations and best practices.
+
+### **Critical Prerequisites: HTTPS/TLS Configuration**
+
+Running Superset without HTTPS (TLS) is not secure. Without it, all network
traffic—including user credentials, session tokens, and sensitive data—is sent
in cleartext and can be easily intercepted.
+
+* **Use a Reverse Proxy:** Your Superset instance should always be deployed
behind a reverse proxy (e.g., Nginx, Traefik) or a load balancer (e.g., AWS
ALB, Google Cloud Load Balancer) that is configured to handle HTTPS termination.
+* **Enforce Modern TLS:** Configure your proxy to enforce TLS 1.2 or higher
with strong, industry-standard cipher suites.
+* **Implement HSTS:** Use the HTTP Strict Transport Security (HSTS) header to
ensure browsers only connect to your Superset instance over HTTPS. This can be
configured in your reverse proxy or within Superset's Talisman settings.
+
+> #### ⚠️ Warning: Never Run Superset on HTTP in Production
+>
+> Exposing Superset directly over HTTP is a critical security risk that
exposes your entire instance to network interception attacks.
+
+### **`SUPERSET_SECRET_KEY` Management (CRITICAL)**
+
+This is the most critical security setting for your Superset instance. It is
used to sign all session cookies and encrypt sensitive information in the
metadata database, such as database connection credentials.
+
+* **Generate a Unique, Strong Key:** A unique key must be generated for every
Superset instance. Use a cryptographically secure method to create it.
+ ```bash
+ # Example using openssl to generate a strong key
+ openssl rand -base64 42
+ ```
+* **Store the Key Securely:** The key must be kept confidential. The
recommended approach is to store it as an environment variable or in a secrets
management system (e.g., AWS Secrets Manager, HashiCorp Vault). **Do not
hardcode the key in `superset_config.py` or commit it to version control.**
+ ```python
+ # In superset_config.py
+ import os
+ SECRET_KEY = os.environ.get('SUPERSET_SECRET_KEY')
+ ```
+
+> #### ⚠️ Warning: Your `SUPERSET_SECRET_KEY` Must Be Unique
+>
+> **NEVER** reuse the same `SUPERSET_SECRET_KEY` across different environments
(e.g., development, staging, production) or different Superset instances.
Reusing a key allows cryptographically signed session cookies to be used across
those instances, which can lead to a full authentication bypass if a cookie is
compromised. Treat this key like a master password.
+
+### **Session Management Security (CRITICAL)**
+
+Properly configuring user sessions is essential to prevent session hijacking
and ensure that sessions are terminated correctly.
+
+#### **Use a Server-Side Session Backend (Strongly Recommended for
Production)**
+
+The default stateless cookie-based session handling presents challenges for
immediate session invalidation upon logout. For all production deployments, we
strongly recommend configuring a server-side session backend like Redis,
Memcached, or a database. This ensures that session data is stored securely on
the server and can be instantly destroyed upon logout, rendering any copied
session cookies immediately useless.
+
+**Example `superset_config.py` for Redis:**
+
+```python
+# superset_config.py
+from redis import Redis
+import os
+
+# 1. Enable server-side sessions
+SESSION_SERVER_SIDE = True
+
+# 2. Choose your backend (e.g., 'redis', 'memcached', 'filesystem',
'sqlalchemy')
+SESSION_TYPE = 'redis'
+
+# 3. Configure your Redis connection
+# Use environment variables for sensitive details
+SESSION_REDIS = Redis(
+ host=os.environ.get('REDIS_HOST', 'localhost'),
+ port=int(os.environ.get('REDIS_PORT', 6379)),
+ password=os.environ.get('REDIS_PASSWORD'),
+ db=int(os.environ.get('REDIS_DB', 0)),
+ ssl=os.environ.get('REDIS_SSL_ENABLED', 'True').lower() == 'true',
+ ssl_cert_reqs='required' # Or another appropriate SSL setting
+)
+
+# 4. Ensure the session cookie is signed for integrity
+SESSION_USE_SIGNER = True
+```
+
+#### **Configure Session Lifetime and Cookie Security Flags**
+
+This is mandatory for *all* deployments, whether stateless or server-side.
+
+```python
+# superset_config.py
+from datetime import timedelta
+
+# Set a short absolute session timeout
+# The default is 31 days, which is NOT recommended for production.
+PERMANENT_SESSION_LIFETIME = timedelta(hours=8)
+
+# Enforce secure cookie flags to prevent browser-based attacks
+SESSION_COOKIE_SECURE = True # Transmit cookie only over HTTPS
+SESSION_COOKIE_HTTPONLY = True # Prevent client-side JS from accessing the
cookie
+SESSION_COOKIE_SAMESITE = 'Lax' # Provide protection against CSRF attacks
+```
+
+### **Authentication and Authorization**
+
+While Superset's built-in database authentication is convenient, for
production it's highly recommended to integrate with an enterprise-grade
identity provider (IdP).
+
+ * **Use an Enterprise IdP:** Configure authentication via OAuth, OIDC, SAML,
or LDAP to leverage your organization's existing identity management system.
This provides benefits like Single Sign-On (SSO), Multi-Factor Authentication
(MFA), and centralized user provisioning/deprovisioning.
+ * **Principle of Least Privilege:** Assign users to the most restrictive
roles necessary for their jobs. Avoid over-provisioning users with Admin or
Alpha roles, and ensure row-level security is applied where appropriate.
+
+### **Content Security Policy (CSP) and Other Headers**
+
+Superset can use Flask-Talisman to set security headers. However, it must be
explicitly enabled.
+
+> #### ⚠️ Important: Talisman is Disabled by Default
+>
+> In Superset 4.0 and later, Talisman is disabled by default
(`TALISMAN_ENABLED = False`). You **must** explicitly enable it in your
`superset_config.py` for the security headers defined in `TALISMAN_CONFIG` to
take effect.
+
+```python
+# superset_config.py
+# The DEBUG flag MUST be set to False in production
+DEBUG = False
+
+# You must explicitly enable Talisman for it to take effect
+TALISMAN_ENABLED = True
+
+# Define a strict Content Security Policy for production
+TALISMAN_CONFIG = {
+ 'content_security_policy': {
+ 'default-src': ["'self'"],
+ 'img-src': ["'self'", 'data:', 'blob:'],
+ 'worker-src': ["'self'", 'blob:'],
+ 'connect-src': [
+ "'self'",
+ '[https://api.mapbox.com](https://api.mapbox.com)',
+ '[https://events.mapbox.com](https://events.mapbox.com)',
+ '[https://tile.openstreetmap.org](https://tile.openstreetmap.org)',
+ '[https://tile.osm.ch](https://tile.osm.ch)',
Review Comment:
### Invalid CSP URL format breaks external connections <sub></sub>
<details>
<summary>Tell me more</summary>
###### What is the issue?
The CSP connect-src URLs are formatted as Markdown links instead of plain
URLs, which will cause CSP policy failures.
###### Why this matters
Content Security Policy expects plain URL strings, not Markdown-formatted
links. This will result in CSP violations when Superset tries to connect to
these external services, breaking map functionality and other features that
depend on these endpoints.
###### Suggested change ∙ *Feature Preview*
Replace the Markdown-formatted URLs with plain URL strings:
```python
'connect-src': [
"'self'",
'https://api.mapbox.com',
'https://events.mapbox.com',
'https://tile.openstreetmap.org',
'https://tile.osm.ch',
],
```
###### Provide feedback to improve future suggestions
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/cf1843c5-bbf5-4e5a-bad5-c1c20de3c51c/upvote)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/cf1843c5-bbf5-4e5a-bad5-c1c20de3c51c?what_not_true=true)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/cf1843c5-bbf5-4e5a-bad5-c1c20de3c51c?what_out_of_scope=true)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/cf1843c5-bbf5-4e5a-bad5-c1c20de3c51c?what_not_in_standard=true)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/cf1843c5-bbf5-4e5a-bad5-c1c20de3c51c)
</details>
<sub>
💬 Looking for more details? Reply to this comment to chat with Korbit.
</sub>
<!--- korbi internal id:97f952ee-982e-4a78-a26d-b4489fbb51f1 -->
[](97f952ee-982e-4a78-a26d-b4489fbb51f1)
##########
docs/docs/security/securing_superset.mdx:
##########
@@ -0,0 +1,205 @@
+---
+title: Securing Your Superset Installation for Production
+sidebar_position: 3
+---
+
+> *This guide applies to Apache Superset version 4.0 and later.*
+
+The default Apache Superset configuration is optimized for ease of use and
development, not for security. For any production deployment, it is
**critical** that you review and apply the following security configurations to
harden your instance, protect user data, and prevent unauthorized access.
+
+This guide provides a comprehensive checklist of essential security
configurations and best practices.
+
+### **Critical Prerequisites: HTTPS/TLS Configuration**
+
+Running Superset without HTTPS (TLS) is not secure. Without it, all network
traffic—including user credentials, session tokens, and sensitive data—is sent
in cleartext and can be easily intercepted.
+
+* **Use a Reverse Proxy:** Your Superset instance should always be deployed
behind a reverse proxy (e.g., Nginx, Traefik) or a load balancer (e.g., AWS
ALB, Google Cloud Load Balancer) that is configured to handle HTTPS termination.
+* **Enforce Modern TLS:** Configure your proxy to enforce TLS 1.2 or higher
with strong, industry-standard cipher suites.
+* **Implement HSTS:** Use the HTTP Strict Transport Security (HSTS) header to
ensure browsers only connect to your Superset instance over HTTPS. This can be
configured in your reverse proxy or within Superset's Talisman settings.
+
+> #### ⚠️ Warning: Never Run Superset on HTTP in Production
+>
+> Exposing Superset directly over HTTP is a critical security risk that
exposes your entire instance to network interception attacks.
+
+### **`SUPERSET_SECRET_KEY` Management (CRITICAL)**
+
+This is the most critical security setting for your Superset instance. It is
used to sign all session cookies and encrypt sensitive information in the
metadata database, such as database connection credentials.
+
+* **Generate a Unique, Strong Key:** A unique key must be generated for every
Superset instance. Use a cryptographically secure method to create it.
+ ```bash
+ # Example using openssl to generate a strong key
+ openssl rand -base64 42
+ ```
+* **Store the Key Securely:** The key must be kept confidential. The
recommended approach is to store it as an environment variable or in a secrets
management system (e.g., AWS Secrets Manager, HashiCorp Vault). **Do not
hardcode the key in `superset_config.py` or commit it to version control.**
+ ```python
+ # In superset_config.py
+ import os
+ SECRET_KEY = os.environ.get('SUPERSET_SECRET_KEY')
+ ```
+
+> #### ⚠️ Warning: Your `SUPERSET_SECRET_KEY` Must Be Unique
+>
+> **NEVER** reuse the same `SUPERSET_SECRET_KEY` across different environments
(e.g., development, staging, production) or different Superset instances.
Reusing a key allows cryptographically signed session cookies to be used across
those instances, which can lead to a full authentication bypass if a cookie is
compromised. Treat this key like a master password.
+
+### **Session Management Security (CRITICAL)**
+
+Properly configuring user sessions is essential to prevent session hijacking
and ensure that sessions are terminated correctly.
+
+#### **Use a Server-Side Session Backend (Strongly Recommended for
Production)**
+
+The default stateless cookie-based session handling presents challenges for
immediate session invalidation upon logout. For all production deployments, we
strongly recommend configuring a server-side session backend like Redis,
Memcached, or a database. This ensures that session data is stored securely on
the server and can be instantly destroyed upon logout, rendering any copied
session cookies immediately useless.
+
+**Example `superset_config.py` for Redis:**
+
+```python
+# superset_config.py
+from redis import Redis
+import os
+
+# 1. Enable server-side sessions
+SESSION_SERVER_SIDE = True
+
+# 2. Choose your backend (e.g., 'redis', 'memcached', 'filesystem',
'sqlalchemy')
+SESSION_TYPE = 'redis'
+
+# 3. Configure your Redis connection
+# Use environment variables for sensitive details
+SESSION_REDIS = Redis(
+ host=os.environ.get('REDIS_HOST', 'localhost'),
+ port=int(os.environ.get('REDIS_PORT', 6379)),
+ password=os.environ.get('REDIS_PASSWORD'),
+ db=int(os.environ.get('REDIS_DB', 0)),
+ ssl=os.environ.get('REDIS_SSL_ENABLED', 'True').lower() == 'true',
+ ssl_cert_reqs='required' # Or another appropriate SSL setting
+)
+
+# 4. Ensure the session cookie is signed for integrity
+SESSION_USE_SIGNER = True
+```
+
+#### **Configure Session Lifetime and Cookie Security Flags**
+
+This is mandatory for *all* deployments, whether stateless or server-side.
+
+```python
+# superset_config.py
+from datetime import timedelta
+
+# Set a short absolute session timeout
+# The default is 31 days, which is NOT recommended for production.
+PERMANENT_SESSION_LIFETIME = timedelta(hours=8)
+
+# Enforce secure cookie flags to prevent browser-based attacks
+SESSION_COOKIE_SECURE = True # Transmit cookie only over HTTPS
+SESSION_COOKIE_HTTPONLY = True # Prevent client-side JS from accessing the
cookie
+SESSION_COOKIE_SAMESITE = 'Lax' # Provide protection against CSRF attacks
+```
+
+### **Authentication and Authorization**
+
+While Superset's built-in database authentication is convenient, for
production it's highly recommended to integrate with an enterprise-grade
identity provider (IdP).
+
+ * **Use an Enterprise IdP:** Configure authentication via OAuth, OIDC, SAML,
or LDAP to leverage your organization's existing identity management system.
This provides benefits like Single Sign-On (SSO), Multi-Factor Authentication
(MFA), and centralized user provisioning/deprovisioning.
+ * **Principle of Least Privilege:** Assign users to the most restrictive
roles necessary for their jobs. Avoid over-provisioning users with Admin or
Alpha roles, and ensure row-level security is applied where appropriate.
+
+### **Content Security Policy (CSP) and Other Headers**
+
+Superset can use Flask-Talisman to set security headers. However, it must be
explicitly enabled.
+
+> #### ⚠️ Important: Talisman is Disabled by Default
+>
+> In Superset 4.0 and later, Talisman is disabled by default
(`TALISMAN_ENABLED = False`). You **must** explicitly enable it in your
`superset_config.py` for the security headers defined in `TALISMAN_CONFIG` to
take effect.
+
+```python
+# superset_config.py
+# The DEBUG flag MUST be set to False in production
+DEBUG = False
+
+# You must explicitly enable Talisman for it to take effect
+TALISMAN_ENABLED = True
+
+# Define a strict Content Security Policy for production
+TALISMAN_CONFIG = {
+ 'content_security_policy': {
+ 'default-src': ["'self'"],
+ 'img-src': ["'self'", 'data:', 'blob:'],
+ 'worker-src': ["'self'", 'blob:'],
+ 'connect-src': [
+ "'self'",
+ '[https://api.mapbox.com](https://api.mapbox.com)',
+ '[https://events.mapbox.com](https://events.mapbox.com)',
+ '[https://tile.openstreetmap.org](https://tile.openstreetmap.org)',
+ '[https://tile.osm.ch](https://tile.osm.ch)',
+ ],
+ 'object-src': "'none'",
+ 'style-src': ["'self'", "'unsafe-inline'"],
+ 'script-src': ["'self'"],
+ },
+ 'force_https': False, # HTTPS should be handled by a reverse proxy
+ 'strict_transport_security': True,
+ 'session_cookie_secure': True,
+ 'frame_options': 'SAMEORIGIN',
+}
+```
+
+### **Database Security**
+
+> #### ❗ Superset is Not a Database Firewall
+>
+> It is essential to understand that **Apache Superset is a data visualization
and exploration platform, not a database firewall or a comprehensive security
solution for your data warehouse.** While Superset provides features to help
manage data access, the ultimate responsibility for securing your underlying
databases lies with your database administrators (DBAs) and security teams.
This includes managing network access, user privileges, and fine-grained
permissions directly within the database. The configurations below are an
important secondary layer of security but should not be your only line of
defense.
+
+ * **Use a Dedicated Database User:** The database connection configured in
Superset should use a dedicated, limited-privilege database user. This user
should only have the minimum required permissions (e.g., `SELECT` on specific
schemas) for the data sources it needs to query. It should **not** have
`INSERT`, `UPDATE`, `DELETE`, or administrative privileges.
+ * **Restrict Dangerous SQL Functions:** To mitigate potential SQL injection
risks, configure the `DISALLOWED_SQL_FUNCTIONS` list in your
`superset_config.py`. Be aware that this is a defense-in-depth measure, not a
substitute for proper database permissions.
+
+### **7. Additional Security Layers**
+
+ * **Web Application Firewall (WAF):** Deploying Superset behind a WAF (e.g.,
Cloudflare, AWS WAF) is strongly recommended. A WAF with a standard ruleset
(like the OWASP Core Rule Set) provides a critical layer of defense against
common attacks like SQL Injection, XSS, and remote code execution.
+
+### **8. Monitoring and Logging**
Review Comment:
### Inconsistent Heading Structure <sub></sub>
<details>
<summary>Tell me more</summary>
###### What is the issue?
Inconsistent heading numbering scheme in the document. Previous sections
don't use numbers, but these sections suddenly introduce numbering.
###### Why this matters
Inconsistent document structure makes it harder to maintain and reference
sections, potentially confusing readers.
###### Suggested change ∙ *Feature Preview*
Remove the numbers from these headings to match the style of other sections:
```markdown
### **Additional Security Layers**
### **Monitoring and Logging**
```
###### Provide feedback to improve future suggestions
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/200ac229-7301-4852-adc1-7b6e4226f332/upvote)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/200ac229-7301-4852-adc1-7b6e4226f332?what_not_true=true)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/200ac229-7301-4852-adc1-7b6e4226f332?what_out_of_scope=true)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/200ac229-7301-4852-adc1-7b6e4226f332?what_not_in_standard=true)
[](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/200ac229-7301-4852-adc1-7b6e4226f332)
</details>
<sub>
💬 Looking for more details? Reply to this comment to chat with Korbit.
</sub>
<!--- korbi internal id:2b3a5a5d-f9af-492b-9e0a-8d9a36a4f572 -->
[](2b3a5a5d-f9af-492b-9e0a-8d9a36a4f572)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]