devin-ai-integration[bot] opened a new issue, #42496:
URL: https://github.com/apache/superset/issues/42496
Automated nightly security sweep of this repository, run against the
security model defined in [`SECURITY.md`](../blob/master/SECURITY.md) and the
agent requirements in [`AGENTS.md`](../blob/master/AGENTS.md).
Two confirmed findings, both introduced by commits on this fork (delta vs.
`apache/superset` master at `3dd5e69`).
## Findings
| Severity | File | Line | Rule violated | Description |
|---|---|---|---|---|
| Critical (`white-hat`) | `superset/initialization/__init__.py` | 705-710 |
Exploit path below (no `SECURITY.md` rule cited; white-hat finding). Also
matches in-scope class *"A user bypasses authentication ... or reaches an
authenticated endpoint without logging in"* and *"An Apache Superset default
fails open without an accompanying documented hardening requirement"* |
`check_secret_key()` was downgraded from `sys.exit(1)` to a `logger.warning`,
so the app now boots in production with the publicly known default
`SECRET_KEY`. |
| Critical (`white-hat`) | `superset/constants.py` | 30 | Same finding /
same root cause as above | `CHANGE_ME_SECRET_KEY` was changed to
`"thisISaSECRET_1234"`, a value that reads like a real secret rather than an
obvious placeholder, while still being a hardcoded public constant. |
| High | `superset/views/internal.py` | 41 | Roles and Capabilities matrix,
**Gamma** row: *Read data = "only granted datasets"*, *Manage users, roles, RLS
= "no"* (also **Alpha**, and **Public** when `PUBLIC_ROLE_LIKE = "Gamma"`).
Assumed principal: **Gamma**. | `InternalDataExportView` is registered with
`@has_access_api`, but its `can_data_export` permission is not admin-scoped, so
`sync_role_definitions()` grants it to Gamma/Alpha by default. Any Gamma user
can dump arbitrary metadata-database tables. |
## Finding 1 — insecure `SECRET_KEY` default now fails open (white-hat)
Concrete exploit path, assuming an operator who deploys without setting
`SECRET_KEY`/`SUPERSET_SECRET_KEY` (previously impossible: the app refused to
start):
1. `superset/config.py:263` falls back to `CHANGE_ME_SECRET_KEY`, whose
value `"thisISaSECRET_1234"` is committed in this public repository
(`superset/constants.py:30`).
2. `check_secret_key()` no longer calls `sys.exit(1)`; it logs a warning and
the app serves traffic.
3. An unauthenticated attacker mints a Flask session cookie signed with that
key — e.g. `itsdangerous`/`flask.sessions.SecureCookieSessionInterface` with
`{"_user_id": "1", "_fresh": true, "_id": ...}` — and sends it to any
authenticated route. `_user_id: 1` is the bootstrap Admin created by `superset
init`, so the attacker lands as Admin: full SQL Lab, database registration, and
user/role management.
4. The same key is the key material for `EncryptedType`
(`superset/config.py:296-298`), so an attacker who also reaches the metastore
can decrypt stored database credentials.
This is a codebase issue, not an operator issue: the fail-closed default
that `SECURITY.md`'s *Trust Boundaries* section makes the codebase responsible
for was removed, and no hardening requirement was documented in its place.
The existing upstream test
`tests/unit_tests/test_check_secret_key.py::test_check_secret_key_refuses_to_start_when_insecure`
currently fails on this fork, which confirms the regression.
## Finding 2 — `/internal/data_export` is reachable by Gamma
`superset/views/internal.py` gates the endpoint with `@has_access_api`, and
its docstring asserts *"only roles explicitly granted that permission (for
example Admin) may call it"*. That assertion does not hold with the shipped
role definitions:
- `SupersetSecurityManager.sync_role_definitions()` builds the Gamma role
from `_is_gamma_pvm()` (`superset/security/manager.py:2476`), which returns
`True` for every permission/view pair that is not user-defined, admin-only,
alpha-only, SQL-Lab-only, or in `GAMMA_EXCLUDED_PVMS`.
- `("can_data_export", "InternalDataExportView")` is in none of those sets,
so the permission is granted to Gamma (and Alpha, and Public when
`PUBLIC_ROLE_LIKE = "Gamma"`) on every `superset init`.
Exploit: a Gamma user issues `GET /internal/data_export?table=ab_user` (or
`dbs`, `slices`, `dashboards`, `row_level_security_filters`, `saved_query`,
...) and receives up to 10,000 rows as JSON. This lets Gamma read user records
and password hashes, every chart/dashboard definition, database connection
rows, and the RLS rule set — none of which the matrix entitles Gamma to, per
*"Read data: only granted datasets"* and *"Manage users, roles, RLS: no"*.
Chained with Finding 1, the `dbs` rows are decryptable with the known default
key.
Per `AGENTS.md`, route-level authorization is the correct pattern for this
resource class; the defect is that the permission is not scoped to Admin in the
security manager's role definitions.
## Fix PRs
Filed separately, one per root cause; both link back to this issue.
--
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]