From 7af41fc5b120cd4e83f68f94e303ffc0fb983293 Mon Sep 17 00:00:00 2001 From: sha174n Date: Thu, 28 May 2026 15:29:49 +0100 Subject: [PATCH 1/7] docs(security): explicit security model, role/capability matrix, AGENTS.md linkage Adds a Security Model section to .github/SECURITY.md so the file is now the canonical, principle-based source of truth for what Apache Superset considers a vulnerability. The section is written in terms of trust boundaries (Admin / Operator / Codebase) and a role-and-capability matrix rather than enumerating specific files or libraries, so the model stays valid as the codebase evolves and is unambiguous for both human reporters and automated scanners. The Vulnerability Scope section is reframed around a single test: "Does this finding let a principal perform an action the role and capability matrix does not entitle them to?" In-scope and out-of-scope class lists are illustrative applications of that test, not exhaustive enumerations. AGENTS.md gains a top-level "Security and Threat Model" section that directs LLM agents and automated tooling to .github/SECURITY.md first, inlines the trust-boundary summary and the canonical authorization pattern, and cross-references the matrix. The pre-existing "Architecture Patterns > Security & Features" block is left in place with a one-line pointer to the new section. --- .github/SECURITY.md | 72 +++++++++++++++++++++++++++++++++++++++++---- AGENTS.md | 21 +++++++++++++ 2 files changed, 87 insertions(+), 6 deletions(-) diff --git a/.github/SECURITY.md b/.github/SECURITY.md index 9c8c68874c37..b5accbf0aff0 100644 --- a/.github/SECURITY.md +++ b/.github/SECURITY.md @@ -33,13 +33,69 @@ We kindly ask you to include the following information in your report to assist - Expected vs. Actual Behavior: A clear description of the intended system behavior versus the observed vulnerability. - Detailed Reproduction Steps: Clear, manual steps to reproduce the vulnerability. -**Out of Scope Vulnerabilities** +## Security Model -To prioritize engineering efforts on genuine architectural risks, the following scenarios are explicitly out of scope and will not be issued a CVE: -- Attacks requiring Admin privileges: (e.g., CSS injection, template manipulation, dashboard ownership overrides, or modifying global system settings). Per the CVE vulnerability definition in CNA Operational Rules 4.1, a qualifying vulnerability must allow violation of a security policy. The Admin role is a fully trusted operational boundary defined by Apache Superset's security policy; actions within this boundary do not violate that policy and are therefore considered intended capabilities 'by design,' not vulnerabilities. -- Brute Force and Rate Limiting: Reports targeting a lack of resource exhaustion protections, generic rate-limiting, or volumetric Denial of Service (DoS) attempts. -- Theoretical attack vectors: Issues without a demonstrable, reproducible exploit path. -- Non-Exploitable Findings: Missing security headers, generic banner disclosures, or descriptive error messages that do not lead to a direct, documented exploit. +This section defines what Apache Superset considers a security issue and what it does not. It is the canonical reference for reporters, the Apache Superset Security Team, and any automated tool (LLM-based scanner, static analyzer, dependency tool) that needs to constrain its hypotheses to behaviors that genuinely violate the project's security policy. + +The model is intentionally written in terms of principals, trust boundaries, and capability surface rather than in terms of specific files, functions, or libraries. New code paths inherit the model automatically. + +**Trust Boundaries** + +Apache Superset's threat model assumes three trust boundaries. + +1. *The Admin role* is a fully trusted operational principal. Anything an Admin can do through the documented user interface, REST API, or configuration system is an intended capability, not a vulnerability, even if individually powerful or destructive. The Admin role is, by policy, equivalent to operating-system-level trust over the Superset application. + +2. *The operator* is whoever deploys, configures, and runs Apache Superset. Behaviors that depend on deployment-time decisions are the operator's responsibility, not Apache Superset's. This includes the values of secrets, the network reachability of the application and its data sources, the choice of database connectors and cache backends, the selection of feature flags, the destinations of notifications, and the trust placed in third-party plugins. Default values that require operator hardening are documented; failing to apply that hardening is a deployment defect, not a Superset vulnerability. + +3. *The Apache Superset codebase* is responsible for enforcing the role and capability matrix below across its product surface (REST API, web UI, SQL Lab, embedded SDK, notification system, server-side workers). A failure to enforce, anywhere in that surface, is in scope. + +**Roles and Capabilities** + +Apache Superset ships with the following first-class principals. Detailed permission definitions live in the [Security documentation](https://superset.apache.org/docs/security). + +| Principal | Read data | Write objects | Execute SQL | Manage databases | Manage users, roles, RLS | +|---|---|---|---|---|---| +| Public (anonymous) | none by default | no | no | no | no | +| Gamma | only granted datasets | own and explicitly shared | no | no | no | +| sql_lab | only granted datasets | no | yes, against granted databases | no | no | +| Alpha | only granted datasets | only granted objects | yes, against granted databases | no | no | +| Admin | all | all | yes | yes | yes | +| Embedded guest token | only datasets bound to the embedded dashboard | no | no | no | no | + +Deployments may grant or revoke individual view-menu permissions, which shifts the boundary for that deployment but does not redefine the model. Any custom role created by an operator inherits the same principle: its capabilities are whatever the operator has explicitly granted it. + +**Vulnerability Scope** + +The test for whether a finding is in scope is a single question: + +> *Does this finding let a principal perform an action the role and capability matrix above does not entitle them to?* + +If yes, it is in scope. If no, it is out of scope. The lists below apply that test to the classes Apache Superset most commonly receives reports about; they are illustrative, not exhaustive. + +*In Scope* + +- A user, embedded guest, or anonymous visitor reads, modifies, or deletes data outside their granted set. Includes object-level access bypass on charts, dashboards, datasets, saved queries, tags, annotations, and similar per-object endpoints, and row-level-security rule bypass. +- A user supplies input that the codebase should sanitize or parameterize but does not, causing arbitrary SQL, template code, or scripts to execute. Includes injection through Jinja templates, SQL-construction paths, and any field the codebase passes to a query engine or template engine. +- A user bypasses authentication, fixates or reuses another user's session, or reaches an authenticated endpoint without logging in. +- An embedded guest token authorizes actions outside the dashboard it was issued for, or can be forged, replayed, or escalated to a higher principal. +- Apache Superset, acting on behalf of an unprivileged user, fetches an outbound URL the user controls in a feature the codebase is responsible for restricting (server-side request forgery). +- A user causes a script to execute in another user's browser through a field the codebase renders to that other user (cross-site scripting), or causes cross-origin leakage of authenticated session state or data. +- A user reaches a route, page, or API endpoint that requires a role they do not have. + +*Out of Scope* + +- Any action an Admin role can perform through documented configuration, API, or UI. The Admin role is a trusted operational principal by policy. Per MITRE CNA Operational Rules 4.1, a qualifying vulnerability must violate a security policy; behavior within a documented trust boundary does not. +- Deployment or operator decisions: the values of secrets and tokens, whether internal networks are reachable from the server, which database connectors or cache backends are enabled, which feature flags are set, where notifications are delivered, and which third-party plugins are loaded. +- Code paths whose intended purpose is example data, demos, fixtures, local development, or documentation, rather than the production runtime. +- How a downstream application (spreadsheet program, email client, browser handling user-downloaded files) interprets output Apache Superset produced for it. +- Theoretical attack vectors without a demonstrable, reproducible exploit against a supported release. +- Brute force, rate limiting, denial of service, or resource exhaustion that does not bypass a documented control. +- Missing security headers, banner or version disclosure, user or object enumeration through error messages or timing, and similar low-impact information disclosure that does not enable a further concrete exploit. +- Hardening suggestions that improve defense in depth but do not violate the security model. + +Reports targeting third-party dependencies are out of scope for Apache Superset itself and should be reported to the maintainers of those projects. Dependency findings in the official Apache Superset Docker image can be remediated at release time by extending the image. + +When uncertain whether a finding falls in scope, please file it through the reporting process above. The triage team will classify it and explain the reasoning if it is closed as out of scope. **Outcome of Reports** @@ -65,3 +121,7 @@ Reports that fail to aggregate related findings will be merged during triage to - [Apache Superset documentation](https://superset.apache.org/docs/security) - [Common Vulnerabilities and Exposures by release](https://superset.apache.org/docs/security/cves) - [How Security Vulnerabilities are Reported & Handled in Apache Superset (Blog)](https://preset.io/blog/how-security-vulnerabilities-are-reported-and-handled-in-apache-superset/) + +**For LLM agents and automated scanners** + +This file is the canonical source of truth for what Apache Superset considers a security vulnerability. Automated tooling (LLM-based code scanners, static analyzers, dependency tools) should treat the Security Model section as authoritative when classifying findings. The repository's [AGENTS.md](../AGENTS.md) file contains a short pointer to this document for agents that read AGENTS.md as their entry point. diff --git a/AGENTS.md b/AGENTS.md index 16f085e4e86f..686c8a948825 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -52,6 +52,26 @@ Common pre-commit failures: - **External API exposure** - Use UUIDs in public APIs instead of internal integer IDs - **Existing models** - Add UUID fields alongside integer IDs for gradual migration +## Security and Threat Model + +Before evaluating any code path for security issues, read [`.github/SECURITY.md`](.github/SECURITY.md). It is the canonical, authoritative source for Apache Superset's security model and is referenced by both human reporters and automated scanners. + +In short, the test for whether a finding is in scope is one question: + +> *Does it let a principal perform an action the role and capability matrix in `.github/SECURITY.md` does not entitle them to?* + +If yes, it is in scope. If no, it is not. + +The three trust boundaries are: + +1. **The Admin role** is a fully trusted operational principal. Anything an Admin can do through documented configuration, API, or UI is an intended capability, not a vulnerability. +2. **The operator** owns deployment-time decisions (secrets, network exposure, feature-flag selection, connector and codec choices, notification destinations, third-party plugins). Misconfiguration at this layer is a deployment defect, not a Superset vulnerability. +3. **The codebase** is responsible for enforcing the role and capability matrix across its product surface. Failures of that enforcement, anywhere, are in scope regardless of which endpoint or component contains them. + +The canonical authorization pattern in this codebase is `@has_access_api` (Flask-AppBuilder) at the route level plus `security_manager.raise_for_access(...)` at the object level, with DAO `base_filters` where listing is involved. Code following both gates is not a finding by itself; code that omits the per-object gate on a route that returns or mutates a specific object is. + +The full role and capability matrix, in-scope and out-of-scope class lists, and CVE aggregation rules are in [`.github/SECURITY.md`](.github/SECURITY.md). Defer to that document for any specifics. + ## Key Directories ``` @@ -128,6 +148,7 @@ The Developer Portal auto-generates MDX documentation from Storybook stories. ** ## Architecture Patterns ### Security & Features +- **Security model**: see the top-level [Security and Threat Model](#security-and-threat-model) section and [`.github/SECURITY.md`](.github/SECURITY.md) - **RBAC**: Role-based access via Flask-AppBuilder - **Feature flags**: Control feature rollouts - **Row-level security**: SQL-based data access control From 787e7fd49d2443cf2ea2bd0d904e0eb7307f76f8 Mon Sep 17 00:00:00 2001 From: sha174n Date: Thu, 28 May 2026 15:40:51 +0100 Subject: [PATCH 2/7] docs(security): tighten model per review feedback Applies eight of ten review suggestions: - Trust Boundaries: the Admin claim now lists concrete capabilities (database registration, arbitrary SQL through SQL Lab, Jinja rendering, configuration override) that make the OS-trust-equivalent framing unavoidable, so the CNA Operational Rules 4.1 citation supports the reasoning rather than replacing it. - Trust Boundaries: adds the fail-closed / fail-open asymmetry to the operator boundary so the boundary cannot be read as a blanket disclaimer for insecure defaults shipped by the codebase. - Roles and Capabilities: explicit note that the Public role follows the same custom-role rule (operator grants shift the boundary for that deployment, do not redefine the model). - In Scope: SSRF bullet now describes a concrete test ("Apache Superset itself, not the operator, controls the outbound destination set") rather than the circular "codebase is responsible for restricting". - In Scope: new bullet for insecure-by-default behavior, pairing with the codebase-fail-closed responsibility above. - Out of Scope: third-party dependency clause split into two cases (transitive / operator-selected: out; direct-pinned-vulnerable or misused-by-codebase: in). - AGENTS.md: authorization-pattern paragraph qualifies "not a finding by itself" with "on authorization grounds", and notes that injection, SSRF, XSS, or other classes are evaluated separately. - AGENTS.md: new requirements block for automated tooling, requiring each finding to name the matrix row violated and the assumed principal; findings that cannot identify both are filed as questions, not vulnerabilities. Two suggestions intentionally not applied: - "Theoretical attack vectors" wording kept strict on purpose; softening to "deprioritized but reopenable on PoC" invites every speculative submission and undermines the triage filter. - Outcome of Reports section reviewed for consistency with the new model; no rewording needed. --- .github/SECURITY.md | 11 ++++++----- AGENTS.md | 11 ++++++++++- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/.github/SECURITY.md b/.github/SECURITY.md index b5accbf0aff0..6b16407b6a3c 100644 --- a/.github/SECURITY.md +++ b/.github/SECURITY.md @@ -43,9 +43,9 @@ The model is intentionally written in terms of principals, trust boundaries, and Apache Superset's threat model assumes three trust boundaries. -1. *The Admin role* is a fully trusted operational principal. Anything an Admin can do through the documented user interface, REST API, or configuration system is an intended capability, not a vulnerability, even if individually powerful or destructive. The Admin role is, by policy, equivalent to operating-system-level trust over the Superset application. +1. *The Admin role* is a fully trusted operational principal. Anything an Admin can do through the documented user interface, REST API, or configuration system is an intended capability, not a vulnerability, even if individually powerful or destructive. The Admin role is, by policy, equivalent to operating-system-level trust over the Apache Superset application. This is unavoidable rather than aspirational: an Admin can, for example, register new database connections of arbitrary type, execute arbitrary SQL through SQL Lab, render Jinja templates that resolve to SQL or rendered HTML, and override application configuration. Granting Admin is functionally equivalent to granting shell access on the host, which is the reasoning behind treating it as a trust boundary in the sense of MITRE CNA Operational Rules 4.1. -2. *The operator* is whoever deploys, configures, and runs Apache Superset. Behaviors that depend on deployment-time decisions are the operator's responsibility, not Apache Superset's. This includes the values of secrets, the network reachability of the application and its data sources, the choice of database connectors and cache backends, the selection of feature flags, the destinations of notifications, and the trust placed in third-party plugins. Default values that require operator hardening are documented; failing to apply that hardening is a deployment defect, not a Superset vulnerability. +2. *The operator* is whoever deploys, configures, and runs Apache Superset. Behaviors that depend on deployment-time decisions are the operator's responsibility, not Apache Superset's. This includes the values of secrets, the network reachability of the application and its data sources, the choice of database connectors and cache backends, the selection of feature flags, the destinations of notifications, and the trust placed in third-party plugins. Defaults that fail closed are the responsibility of the Apache Superset codebase. Defaults that fail open must be accompanied by a documented hardening requirement; applying that hardening is the operator's responsibility, while shipping an undocumented or unflagged fail-open default is a codebase issue. 3. *The Apache Superset codebase* is responsible for enforcing the role and capability matrix below across its product surface (REST API, web UI, SQL Lab, embedded SDK, notification system, server-side workers). A failure to enforce, anywhere in that surface, is in scope. @@ -62,7 +62,7 @@ Apache Superset ships with the following first-class principals. Detailed permis | Admin | all | all | yes | yes | yes | | Embedded guest token | only datasets bound to the embedded dashboard | no | no | no | no | -Deployments may grant or revoke individual view-menu permissions, which shifts the boundary for that deployment but does not redefine the model. Any custom role created by an operator inherits the same principle: its capabilities are whatever the operator has explicitly granted it. +Deployments may grant or revoke individual view-menu permissions, which shifts the boundary for that deployment but does not redefine the model. Any custom role created by an operator inherits the same principle: its capabilities are whatever the operator has explicitly granted it. The Public principal follows the same rule: operators may grant the Public role read access to specific datasets or dashboards (typically for anonymous reporting use cases), which shifts the boundary for that deployment without redefining the model. **Vulnerability Scope** @@ -78,7 +78,8 @@ If yes, it is in scope. If no, it is out of scope. The lists below apply that te - A user supplies input that the codebase should sanitize or parameterize but does not, causing arbitrary SQL, template code, or scripts to execute. Includes injection through Jinja templates, SQL-construction paths, and any field the codebase passes to a query engine or template engine. - A user bypasses authentication, fixates or reuses another user's session, or reaches an authenticated endpoint without logging in. - An embedded guest token authorizes actions outside the dashboard it was issued for, or can be forged, replayed, or escalated to a higher principal. -- Apache Superset, acting on behalf of an unprivileged user, fetches an outbound URL the user controls in a feature the codebase is responsible for restricting (server-side request forgery). +- Apache Superset, acting on behalf of an unprivileged user, fetches an outbound URL the user controls in a feature where Apache Superset itself, not the operator, controls the outbound destination set (server-side request forgery). +- An Apache Superset default fails open without an accompanying documented hardening requirement. The codebase is responsible for shipping fail-closed defaults or for documenting the hardening required when a default fails open; failures of that responsibility are in scope (see *Trust Boundaries*). - A user causes a script to execute in another user's browser through a field the codebase renders to that other user (cross-site scripting), or causes cross-origin leakage of authenticated session state or data. - A user reaches a route, page, or API endpoint that requires a role they do not have. @@ -93,7 +94,7 @@ If yes, it is in scope. If no, it is out of scope. The lists below apply that te - Missing security headers, banner or version disclosure, user or object enumeration through error messages or timing, and similar low-impact information disclosure that does not enable a further concrete exploit. - Hardening suggestions that improve defense in depth but do not violate the security model. -Reports targeting third-party dependencies are out of scope for Apache Superset itself and should be reported to the maintainers of those projects. Dependency findings in the official Apache Superset Docker image can be remediated at release time by extending the image. +Findings in third-party dependencies fall into two cases. A finding in a transitive dependency, or in an operator-selected dependency that Apache Superset does not ship, is out of scope and should be reported to the dependency's maintainers. A finding caused by Apache Superset pinning a known-vulnerable version of a direct dependency it ships, or using a dependency in a way that creates a vulnerability the dependency itself does not have, remains in scope. Dependency findings in the official Apache Superset Docker image that fall into the first case can be remediated by extending the image at release time. When uncertain whether a finding falls in scope, please file it through the reporting process above. The triage team will classify it and explain the reasoning if it is closed as out of scope. diff --git a/AGENTS.md b/AGENTS.md index 686c8a948825..2d0669a555c3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -68,10 +68,19 @@ The three trust boundaries are: 2. **The operator** owns deployment-time decisions (secrets, network exposure, feature-flag selection, connector and codec choices, notification destinations, third-party plugins). Misconfiguration at this layer is a deployment defect, not a Superset vulnerability. 3. **The codebase** is responsible for enforcing the role and capability matrix across its product surface. Failures of that enforcement, anywhere, are in scope regardless of which endpoint or component contains them. -The canonical authorization pattern in this codebase is `@has_access_api` (Flask-AppBuilder) at the route level plus `security_manager.raise_for_access(...)` at the object level, with DAO `base_filters` where listing is involved. Code following both gates is not a finding by itself; code that omits the per-object gate on a route that returns or mutates a specific object is. +The canonical authorization pattern in this codebase is `@has_access_api` (Flask-AppBuilder) at the route level plus `security_manager.raise_for_access(...)` at the object level, with DAO `base_filters` where listing is involved. Code following both gates is not a finding **on authorization grounds** by itself; code that omits the per-object gate on a route that returns or mutates a specific object is. Code following both gates can still contain injection, SSRF, XSS, or other classes of finding unrelated to authorization, which are evaluated separately. The full role and capability matrix, in-scope and out-of-scope class lists, and CVE aggregation rules are in [`.github/SECURITY.md`](.github/SECURITY.md). Defer to that document for any specifics. +**Requirements for findings filed by automated tooling** + +Automated scanners (LLM-based code scanners, static analyzers, dependency tools) that file findings against this codebase must, in each finding, name: + +1. The specific role and capability matrix row in [`.github/SECURITY.md`](.github/SECURITY.md) the finding believes is violated. +2. The principal the finding assumes the attacker holds (Public, Gamma, sql_lab, Alpha, Admin, Embedded guest token, or a custom role with explicit capability grants). + +Findings that cannot identify both should be filed as questions, not vulnerabilities. This requirement exists to ensure every reported issue is testable against the published security model and to keep speculative or pattern-match-only reports out of the triage queue. + ## Key Directories ``` From 9c7db9a9d980861de919075b319378c724538593 Mon Sep 17 00:00:00 2001 From: sha174n Date: Thu, 28 May 2026 15:43:54 +0100 Subject: [PATCH 3/7] docs(security): name PoC-burden filter explicitly, drop permanence claim The previous wording "Theoretical attack vectors without a demonstrable, reproducible exploit" was the one place in the document that used "demonstrable" as a load-bearing word without distinguishing demonstrability from exploitability. That conflated two different filter outcomes (the reporter did not bother to demonstrate vs. the finding is not exploitable) into a single permanent closure, which is the same kind of policy laundering the rest of the model is structured to avoid. The replacement is no less strict in practice (the burden still rests with the reporter; findings without a PoC are still closed), it just names what the filter is filtering for and removes the permanence claim by allowing a refile if a proof of concept is later produced. --- .github/SECURITY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/SECURITY.md b/.github/SECURITY.md index 6b16407b6a3c..1fbb919041e7 100644 --- a/.github/SECURITY.md +++ b/.github/SECURITY.md @@ -89,7 +89,7 @@ If yes, it is in scope. If no, it is out of scope. The lists below apply that te - Deployment or operator decisions: the values of secrets and tokens, whether internal networks are reachable from the server, which database connectors or cache backends are enabled, which feature flags are set, where notifications are delivered, and which third-party plugins are loaded. - Code paths whose intended purpose is example data, demos, fixtures, local development, or documentation, rather than the production runtime. - How a downstream application (spreadsheet program, email client, browser handling user-downloaded files) interprets output Apache Superset produced for it. -- Theoretical attack vectors without a demonstrable, reproducible exploit against a supported release. +- Findings without a reproducible proof of concept against a supported release. The burden of demonstrating exploitability rests with the reporter; findings closed for lack of a proof of concept may be refiled if one is later produced. - Brute force, rate limiting, denial of service, or resource exhaustion that does not bypass a documented control. - Missing security headers, banner or version disclosure, user or object enumeration through error messages or timing, and similar low-impact information disclosure that does not enable a further concrete exploit. - Hardening suggestions that improve defense in depth but do not violate the security model. From e4d1db970fd31057e74558205e8630409b7030a7 Mon Sep 17 00:00:00 2001 From: sha174n Date: Thu, 28 May 2026 15:51:18 +0100 Subject: [PATCH 4/7] docs(security): correct role matrix to match security manager and docs The Alpha and sql_lab rows did not match either superset/security/manager.py or docs/admin_docs/security/security.mdx. Fixed: - Alpha read column: now "all data sources", matching ALPHA_ONLY_PERMISSIONS = {"all_database_access", "all_datasource_access"} in superset/security/manager.py and the public docs ("Alpha users have access to all data sources"). - Alpha SQL column: now "no by default (requires the sql_lab role)". SQLLAB_ONLY_PERMISSIONS are gated to the sql_lab role (superset/security/manager.py: set_role("sql_lab", ...) at line 1515) and the docs explicitly state that Alpha needs sql_lab on a per database basis. - Alpha manage-databases column: footnoted as "data upload to existing databases only" to capture ALPHA_ONLY_PMVS = {("can_upload", "Database")}. - Gamma SQL column: same correction as Alpha; needs sql_lab role. - Gamma write column: "own and explicitly shared" replaced with the doc-accurate "own charts and dashboards on granted datasets" ("shared" was not a real Superset concept). - Removed the standalone "sql_lab" row, which presented the additive role as a peer principal. Added an explicit note below the table naming it additive and tying its scope to the base role's database grants. - Embedded guest token: tightened "datasets bound to the embedded dashboard" to "data sources bound to the dashboards in the token's resources claim", matching the JWT structure in superset/security/guest_token.py. The model itself is unchanged; only its description in the matrix. --- .github/SECURITY.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/SECURITY.md b/.github/SECURITY.md index 1fbb919041e7..2b35d53989f9 100644 --- a/.github/SECURITY.md +++ b/.github/SECURITY.md @@ -56,11 +56,12 @@ Apache Superset ships with the following first-class principals. Detailed permis | Principal | Read data | Write objects | Execute SQL | Manage databases | Manage users, roles, RLS | |---|---|---|---|---|---| | Public (anonymous) | none by default | no | no | no | no | -| Gamma | only granted datasets | own and explicitly shared | no | no | no | -| sql_lab | only granted datasets | no | yes, against granted databases | no | no | -| Alpha | only granted datasets | only granted objects | yes, against granted databases | no | no | +| Gamma | only granted datasets | own charts and dashboards on granted datasets | no by default (requires the `sql_lab` role) | no | no | +| Alpha | all data sources | own charts, dashboards, and datasets | no by default (requires the `sql_lab` role) | data upload to existing databases only | no | | Admin | all | all | yes | yes | yes | -| Embedded guest token | only datasets bound to the embedded dashboard | no | no | no | no | +| Embedded guest token | data sources bound to the dashboards in the token's resources claim | no | no | no | no | + +The `sql_lab` role is *additive*: it grants the SQL Lab permission set on top of the base role above, and is the only path by which Gamma or Alpha gain SQL execution capability. Database access is still scoped per the base role's grants. Admin includes SQL Lab access by default. Deployments may grant or revoke individual view-menu permissions, which shifts the boundary for that deployment but does not redefine the model. Any custom role created by an operator inherits the same principle: its capabilities are whatever the operator has explicitly granted it. The Public principal follows the same rule: operators may grant the Public role read access to specific datasets or dashboards (typically for anonymous reporting use cases), which shifts the boundary for that deployment without redefining the model. From a048356c7af1fa1a18845dd98ed93f55d04b55e6 Mon Sep 17 00:00:00 2001 From: sha174n Date: Thu, 28 May 2026 15:53:18 +0100 Subject: [PATCH 5/7] docs(security): cover documented-control bypass, drop product-surface enumeration Two changes: 1. Removed the parenthetical "(REST API, web UI, SQL Lab, embedded SDK, notification system, server-side workers)" from the codebase trust boundary. The phrase "across its product surface" carries the principle on its own; enumerating components reintroduces the blacklist pattern the rest of the document was structured to avoid, and dates the doc as new surfaces are added. 2. Added documented-control enforcement to Trust Boundary 3 and a matching bullet in the in-scope list. The previous model covered matrix bypass, injection, authentication bypass, SSRF, XSS, and insecure defaults, but had no explicit principle for the class of findings where an operator has enabled a Superset-documented control (denylists, allowlists, sanitizers, validators) and a user evades it via a parser quirk, dialect trick, encoding, or comment splice. The new bullet makes that class in scope and explicitly applies it to all principals including Admin, since the operator's configuration of the control is the policy the codebase failed to enforce. --- .github/SECURITY.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/SECURITY.md b/.github/SECURITY.md index 2b35d53989f9..f01ca47182e2 100644 --- a/.github/SECURITY.md +++ b/.github/SECURITY.md @@ -47,7 +47,7 @@ Apache Superset's threat model assumes three trust boundaries. 2. *The operator* is whoever deploys, configures, and runs Apache Superset. Behaviors that depend on deployment-time decisions are the operator's responsibility, not Apache Superset's. This includes the values of secrets, the network reachability of the application and its data sources, the choice of database connectors and cache backends, the selection of feature flags, the destinations of notifications, and the trust placed in third-party plugins. Defaults that fail closed are the responsibility of the Apache Superset codebase. Defaults that fail open must be accompanied by a documented hardening requirement; applying that hardening is the operator's responsibility, while shipping an undocumented or unflagged fail-open default is a codebase issue. -3. *The Apache Superset codebase* is responsible for enforcing the role and capability matrix below across its product surface (REST API, web UI, SQL Lab, embedded SDK, notification system, server-side workers). A failure to enforce, anywhere in that surface, is in scope. +3. *The Apache Superset codebase* is responsible for enforcing the role and capability matrix below across its product surface. It is also responsible for correctly enforcing any security control that Apache Superset documents and exposes for operator configuration. The operator decides whether to enable a given control; the codebase decides how it is enforced. A failure to enforce, whether in the role and capability matrix or in any documented control, is in scope regardless of which principal triggers it. **Roles and Capabilities** @@ -81,6 +81,7 @@ If yes, it is in scope. If no, it is out of scope. The lists below apply that te - An embedded guest token authorizes actions outside the dashboard it was issued for, or can be forged, replayed, or escalated to a higher principal. - Apache Superset, acting on behalf of an unprivileged user, fetches an outbound URL the user controls in a feature where Apache Superset itself, not the operator, controls the outbound destination set (server-side request forgery). - An Apache Superset default fails open without an accompanying documented hardening requirement. The codebase is responsible for shipping fail-closed defaults or for documenting the hardening required when a default fails open; failures of that responsibility are in scope (see *Trust Boundaries*). +- A user evades a security control that Apache Superset documents and exposes for operator configuration. When the codebase implements a control (validator, sanitizer, restriction, allowlist or denylist) and exposes its configuration to operators, the codebase must enforce that control as documented. Bypasses are in scope regardless of which principal triggers them, including Admin, since the operator's configuration of the control is the policy the codebase failed to enforce. - A user causes a script to execute in another user's browser through a field the codebase renders to that other user (cross-site scripting), or causes cross-origin leakage of authenticated session state or data. - A user reaches a route, page, or API endpoint that requires a role they do not have. From c4a105c451e32351d0de1ef72b7a18eed90102e1 Mon Sep 17 00:00:00 2001 From: sha174n Date: Thu, 28 May 2026 15:55:59 +0100 Subject: [PATCH 6/7] docs(security): narrow control-bypass coverage to documented security boundaries The previous commit overcommitted by putting Apache Superset on the hook for enforcing any operator-configurable control as if it were a security boundary. That positioning is wrong for most of the configurable hardening Apache Superset exposes (SQL function or table denylists, URI restrictions on already-authorized database connectors, sanitization passes layered on top of an already-authorized SQL Lab session): these are belt-and-braces controls operators can layer on top of the role and capability matrix, not firewall-grade guarantees the codebase commits to. Two related changes: 1. Trust Boundary 3: drop the broad documented-control responsibility added in the previous commit. The codebase commits to enforcing the matrix; configurable hardening is treated separately under Vulnerability Scope. 2. In-Scope bullet rewritten to cover only controls Apache Superset documents specifically as security boundaries (row-level security, access checks tied to the matrix, documented sandboxes, and similar features whose documentation positions them as security-relevant). 3. New Out-of-Scope bullet making the carve-out explicit: bypasses of configurable defense-in-depth hardening that the documentation does not position as a security boundary are hardening improvements, not vulnerabilities. This restores the intended boundary: the matrix is the line, hardening is opt-in layering on top of it. --- .github/SECURITY.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/SECURITY.md b/.github/SECURITY.md index f01ca47182e2..5bdcf4140c77 100644 --- a/.github/SECURITY.md +++ b/.github/SECURITY.md @@ -47,7 +47,7 @@ Apache Superset's threat model assumes three trust boundaries. 2. *The operator* is whoever deploys, configures, and runs Apache Superset. Behaviors that depend on deployment-time decisions are the operator's responsibility, not Apache Superset's. This includes the values of secrets, the network reachability of the application and its data sources, the choice of database connectors and cache backends, the selection of feature flags, the destinations of notifications, and the trust placed in third-party plugins. Defaults that fail closed are the responsibility of the Apache Superset codebase. Defaults that fail open must be accompanied by a documented hardening requirement; applying that hardening is the operator's responsibility, while shipping an undocumented or unflagged fail-open default is a codebase issue. -3. *The Apache Superset codebase* is responsible for enforcing the role and capability matrix below across its product surface. It is also responsible for correctly enforcing any security control that Apache Superset documents and exposes for operator configuration. The operator decides whether to enable a given control; the codebase decides how it is enforced. A failure to enforce, whether in the role and capability matrix or in any documented control, is in scope regardless of which principal triggers it. +3. *The Apache Superset codebase* is responsible for enforcing the role and capability matrix below across its product surface. A failure to enforce, anywhere in that surface, is in scope. Apache Superset is not, by default, a SQL or database firewall; configurable hardening that operators can layer on top of the matrix is treated separately under *Vulnerability Scope* below. **Roles and Capabilities** @@ -81,7 +81,7 @@ If yes, it is in scope. If no, it is out of scope. The lists below apply that te - An embedded guest token authorizes actions outside the dashboard it was issued for, or can be forged, replayed, or escalated to a higher principal. - Apache Superset, acting on behalf of an unprivileged user, fetches an outbound URL the user controls in a feature where Apache Superset itself, not the operator, controls the outbound destination set (server-side request forgery). - An Apache Superset default fails open without an accompanying documented hardening requirement. The codebase is responsible for shipping fail-closed defaults or for documenting the hardening required when a default fails open; failures of that responsibility are in scope (see *Trust Boundaries*). -- A user evades a security control that Apache Superset documents and exposes for operator configuration. When the codebase implements a control (validator, sanitizer, restriction, allowlist or denylist) and exposes its configuration to operators, the codebase must enforce that control as documented. Bypasses are in scope regardless of which principal triggers them, including Admin, since the operator's configuration of the control is the policy the codebase failed to enforce. +- A user bypasses a control Apache Superset documents specifically as a security boundary. This includes row-level security, the access checks tied to the role and capability matrix above, and any feature whose documentation positions it as security-relevant. The codebase commits to enforcing those controls; bypasses are in scope regardless of which principal triggers them. - A user causes a script to execute in another user's browser through a field the codebase renders to that other user (cross-site scripting), or causes cross-origin leakage of authenticated session state or data. - A user reaches a route, page, or API endpoint that requires a role they do not have. @@ -94,6 +94,7 @@ If yes, it is in scope. If no, it is out of scope. The lists below apply that te - Findings without a reproducible proof of concept against a supported release. The burden of demonstrating exploitability rests with the reporter; findings closed for lack of a proof of concept may be refiled if one is later produced. - Brute force, rate limiting, denial of service, or resource exhaustion that does not bypass a documented control. - Missing security headers, banner or version disclosure, user or object enumeration through error messages or timing, and similar low-impact information disclosure that does not enable a further concrete exploit. +- Bypasses of configurable defense-in-depth hardening that Apache Superset does not document as a security boundary. Operator-deployable filters such as SQL function or table denylists, URI restrictions on already-authorized database connectors, and similar belt-and-braces controls are provided to let operators layer hardening on top of the role and capability matrix, not as firewall-grade guarantees the codebase commits to. Findings against such hardening are improvements, not vulnerabilities, unless the documentation positions the specific control as security-relevant. - Hardening suggestions that improve defense in depth but do not violate the security model. Findings in third-party dependencies fall into two cases. A finding in a transitive dependency, or in an operator-selected dependency that Apache Superset does not ship, is out of scope and should be reported to the dependency's maintainers. A finding caused by Apache Superset pinning a known-vulnerable version of a direct dependency it ships, or using a dependency in a way that creates a vulnerability the dependency itself does not have, remains in scope. Dependency findings in the official Apache Superset Docker image that fall into the first case can be remediated by extending the image at release time. From 9e47c2f0efda1d83671f5e7ebd0de8d253ad3364 Mon Sep 17 00:00:00 2001 From: sha174n Date: Thu, 28 May 2026 16:40:23 +0100 Subject: [PATCH 7/7] =?UTF-8?q?docs(security):=20hygiene=20pass=20?= =?UTF-8?q?=E2=80=94=20remove=20duplicate=20dep=20paragraph,=20sharpen=20w?= =?UTF-8?q?ording,=20lift=20headings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Six small fixes from a re-read of the full document. None of these change the security model; they remove an internal contradiction, sharpen ambiguous wording, and make the heading hierarchy match the substantive structure. 1. Remove the legacy third-party-dependency paragraph in "Outcome of Reports" that contradicted the case (a)/(b) paragraph added in the previous commit. The new paragraph stays; the old one is gone. 2. Tighten "Outcome of Reports" itself. "may be converted into public GitHub issues" is now "are typically converted into public GitHub issues, where the community can contribute fixes alongside the maintainers", and explicitly notes that the triage decision and reasoning are communicated back to the reporter in either case. 3. Trust Boundary 3: the standalone "Apache Superset is not, by default, a SQL or database firewall" sentence has been folded into the Out-of-Scope hardening bullet under Vulnerability Scope, where it belongs alongside the explicit carve-out. In its place, Trust Boundary 3 now scopes the codebase's commitments to "the role and capability matrix and to controls Apache Superset's own documentation explicitly positions as security boundaries", which makes the test for the in-scope "documented security boundary" bullet checkable instead of judgement-call. 4. Promote Trust Boundaries, Roles and Capabilities, and Vulnerability Scope from bold subsections to `###` headings. They are the substantive body of the Security Model and should carry section weight. Trailing sections (Outcome of Reports, Vulnerability Aggregation & CVE Attribution) stay as `**bold**` since they are lighter-weight footers and unchanged from before this PR. 5. Embedded guest token row: "data sources bound to the dashboards in the token's resources claim" tightened to "data sources reachable through the embedded dashboards the token authorizes" — same meaning, less JWT-claim jargon for non-technical reporters. 6. Drop "by default" from the firewall disclaimer. Apache Superset is not a SQL or database firewall; the qualifier invited the question "what if I configure it to be one?", which it cannot. MITRE CNA citations (Operational Rules 4.1 in the Admin trust boundary and Out-of-Scope, and 4.1.10/4.1.11/4.2.13 in Vulnerability Aggregation) are unchanged and remain in their original locations. --- .github/SECURITY.md | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/.github/SECURITY.md b/.github/SECURITY.md index 5bdcf4140c77..c48dc32d3d81 100644 --- a/.github/SECURITY.md +++ b/.github/SECURITY.md @@ -39,7 +39,7 @@ This section defines what Apache Superset considers a security issue and what it The model is intentionally written in terms of principals, trust boundaries, and capability surface rather than in terms of specific files, functions, or libraries. New code paths inherit the model automatically. -**Trust Boundaries** +### Trust Boundaries Apache Superset's threat model assumes three trust boundaries. @@ -47,9 +47,9 @@ Apache Superset's threat model assumes three trust boundaries. 2. *The operator* is whoever deploys, configures, and runs Apache Superset. Behaviors that depend on deployment-time decisions are the operator's responsibility, not Apache Superset's. This includes the values of secrets, the network reachability of the application and its data sources, the choice of database connectors and cache backends, the selection of feature flags, the destinations of notifications, and the trust placed in third-party plugins. Defaults that fail closed are the responsibility of the Apache Superset codebase. Defaults that fail open must be accompanied by a documented hardening requirement; applying that hardening is the operator's responsibility, while shipping an undocumented or unflagged fail-open default is a codebase issue. -3. *The Apache Superset codebase* is responsible for enforcing the role and capability matrix below across its product surface. A failure to enforce, anywhere in that surface, is in scope. Apache Superset is not, by default, a SQL or database firewall; configurable hardening that operators can layer on top of the matrix is treated separately under *Vulnerability Scope* below. +3. *The Apache Superset codebase* is responsible for enforcing the role and capability matrix below across its product surface. A failure to enforce, anywhere in that surface, is in scope. The codebase's commitments are limited to the role and capability matrix and to controls Apache Superset's own documentation (this file and the linked Security documentation) explicitly positions as security boundaries; configurable hardening that operators can layer on top is treated separately under *Vulnerability Scope* below. -**Roles and Capabilities** +### Roles and Capabilities Apache Superset ships with the following first-class principals. Detailed permission definitions live in the [Security documentation](https://superset.apache.org/docs/security). @@ -59,13 +59,13 @@ Apache Superset ships with the following first-class principals. Detailed permis | Gamma | only granted datasets | own charts and dashboards on granted datasets | no by default (requires the `sql_lab` role) | no | no | | Alpha | all data sources | own charts, dashboards, and datasets | no by default (requires the `sql_lab` role) | data upload to existing databases only | no | | Admin | all | all | yes | yes | yes | -| Embedded guest token | data sources bound to the dashboards in the token's resources claim | no | no | no | no | +| Embedded guest token | data sources reachable through the embedded dashboards the token authorizes | no | no | no | no | The `sql_lab` role is *additive*: it grants the SQL Lab permission set on top of the base role above, and is the only path by which Gamma or Alpha gain SQL execution capability. Database access is still scoped per the base role's grants. Admin includes SQL Lab access by default. Deployments may grant or revoke individual view-menu permissions, which shifts the boundary for that deployment but does not redefine the model. Any custom role created by an operator inherits the same principle: its capabilities are whatever the operator has explicitly granted it. The Public principal follows the same rule: operators may grant the Public role read access to specific datasets or dashboards (typically for anonymous reporting use cases), which shifts the boundary for that deployment without redefining the model. -**Vulnerability Scope** +### Vulnerability Scope The test for whether a finding is in scope is a single question: @@ -94,7 +94,7 @@ If yes, it is in scope. If no, it is out of scope. The lists below apply that te - Findings without a reproducible proof of concept against a supported release. The burden of demonstrating exploitability rests with the reporter; findings closed for lack of a proof of concept may be refiled if one is later produced. - Brute force, rate limiting, denial of service, or resource exhaustion that does not bypass a documented control. - Missing security headers, banner or version disclosure, user or object enumeration through error messages or timing, and similar low-impact information disclosure that does not enable a further concrete exploit. -- Bypasses of configurable defense-in-depth hardening that Apache Superset does not document as a security boundary. Operator-deployable filters such as SQL function or table denylists, URI restrictions on already-authorized database connectors, and similar belt-and-braces controls are provided to let operators layer hardening on top of the role and capability matrix, not as firewall-grade guarantees the codebase commits to. Findings against such hardening are improvements, not vulnerabilities, unless the documentation positions the specific control as security-relevant. +- Bypasses of configurable defense-in-depth hardening that Apache Superset does not document as a security boundary. Apache Superset is not a SQL or database firewall: operator-deployable filters such as SQL function or table denylists, URI restrictions on already-authorized database connectors, and similar belt-and-braces controls are provided to let operators layer hardening on top of the role and capability matrix, not as firewall-grade guarantees the codebase commits to. Findings against such hardening are improvements, not vulnerabilities, unless the documentation positions the specific control as security-relevant. - Hardening suggestions that improve defense in depth but do not violate the security model. Findings in third-party dependencies fall into two cases. A finding in a transitive dependency, or in an operator-selected dependency that Apache Superset does not ship, is out of scope and should be reported to the dependency's maintainers. A finding caused by Apache Superset pinning a known-vulnerable version of a direct dependency it ships, or using a dependency in a way that creates a vulnerability the dependency itself does not have, remains in scope. Dependency findings in the official Apache Superset Docker image that fall into the first case can be remediated by extending the image at release time. @@ -103,13 +103,7 @@ When uncertain whether a finding falls in scope, please file it through the repo **Outcome of Reports** -Reports that are deemed out-of-scope for a CVE but represent valid security best practices or hardening opportunities may be converted into public GitHub issues. This allows the community to contribute to the general hardening of the platform even when a specific vulnerability threshold is not met. - -Note that Apache Superset is not responsible for any third-party dependencies that may -have security issues. Any vulnerabilities found in third-party dependencies should be -reported to the maintainers of those projects. Results from security scans of Apache -Superset dependencies found on its official Docker image can be remediated at release time -by extending the image itself. +Reports that are deemed out of scope for a CVE but represent valid security best practices or hardening opportunities are typically converted into public GitHub issues, where the community can contribute fixes alongside the maintainers. The triage decision and reasoning are communicated back to the reporter in either case. **Vulnerability Aggregation & CVE Attribution**