Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion UPDATING.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ assists people when migrating to a new version.
moves to that DB: avoid running old and new versions side by side, and drain
in-flight tasks before upgrading.

- [45186](https://github.com/apache/superset/pull/45186): Sets pyarrow>=23.0.1
Comment thread
sadpandajoe marked this conversation as resolved.
Resolved
in superset-core (without an upper ceiling) and explicitly bounds
msgpack>=1.2.3,<1.3.0 in requirements/base.in. The relaxed floor in core
resolves CVE-2026-25087 while preserving compatibility for downstream
extensions, whereas container images and application builds continue to
enforce the narrower window via requirements/base.in and
requirements/base.txt.

- Refreshing a dataset's columns from its source (the "Sync columns from
source" button, `PUT /api/v1/dataset/<id>?override_columns=true`, or
`PUT /api/v1/dataset/<id>/refresh`) no longer resets **Is dimension** and
Expand Down Expand Up @@ -177,7 +185,6 @@ assists people when migrating to a new version.
time-axis bounds; time-series offsets and separate inner-bound queries replace
ranges on their selected axis. Retained predicates can narrow results where
earlier releases discarded them.

- **Semantic NULL filters and provider SDK upgrade.** Semantic filters normalize
UI NULL/empty-string selections. Mixed positive NULL membership uses `OrFilter`,
which every semantic provider must render; previously NULL rows could be
Expand Down
4 changes: 4 additions & 0 deletions docs/admin_docs/security/cves.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,7 @@ sidebar_position: 2
| CVE-2022-43720 | Improper rendering of user input | < 2.0.1 or < 1.5.2 |
| CVE-2022-43721 | Open Redirect Vulnerability | < 2.0.1 or < 1.5.2 |
| CVE-2022-45438 | Dashboard metadata information leak | < 2.0.1 or < 1.5.2 |

---

For third-party container scan findings and remediation guidance, see the [Dependency Vulnerability Remediation Guide](./dependency-vulnerability-remediation.mdx).
97 changes: 97 additions & 0 deletions docs/admin_docs/security/dependency-vulnerability-remediation.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
---
title: Dependency Vulnerability Remediation & Scanner Guidance
sidebar_position: 3
---

# Dependency Vulnerability Remediation & Container Scanner Guidance

This guide addresses third-party dependency vulnerabilities reported by container security scanners (such as Trivy, Grype, and Snyk) in Apache Superset environments, specifically regarding dependency constraint handling for cryptography, msgpack, and pyarrow (referencing issue #45087).

## 1. Vulnerability Applicability & Risk Assessment

When security scanners evaluate Apache Superset container images, findings frequently arise in transitive or pinned direct dependencies. The table below details the applicability and actual exploitability surface of recently reported findings:

| Package | Finding ID | Severity | Upstream Fixed Version | Superset Target Floor | Superset Code Path & Exploitability Analysis |
| :--- | :--- | :--- | :--- | :--- | :--- |
| **cryptography** | CVE-2026-69247 | HIGH | `50.0.0` | `>=50.0.2` | Bleichenbacher timing and error decryption oracle in PKCS#7 EnvelopedData. Superset does not consume, parse, or decrypt PKCS#7 or S/MIME enveloped data. |
| **cryptography** | CVE-2026-69249 | HIGH | `49.0.0` | `>=50.0.2` | X.509 path-building algorithm denial of service with duplicate intermediate certificates. Superset parses leaf database SSL certificates using `load_pem_x509_certificate` and does not build untrusted X.509 certification paths during web request processing. |
| **cryptography** | CVE-2026-69248 | MEDIUM | `49.0.0` | `>=50.0.2` | Wildcard-DNS name-constraint bypass in the cryptography X.509 certificate verifier (`cryptography.x509.verification.PolicyBuilder`). Superset parses leaf database SSL certificates using `load_pem_x509_certificate` and does not invoke cryptography's certificate verification or path validation APIs. TLS transport verification is performed by underlying network and database drivers via OpenSSL/Python `ssl`. |
| **cryptography** | GHSA-537c-gmf6-5ccf (CVE-2026-34180) | HIGH | `48.0.1` | `>=50.0.2` | Vulnerabilities in OpenSSL bundled in binary wheels (remediated in upstream wheels from 48.0.1 and pinned to 50.0.2 in Superset locked requirements). In production container deployments following Option A, the runtime libraries are updated; raw cryptographic primitives are not exposed to untrusted external callers. |
| **msgpack** | GHSA-6v7p-g79w-8964 (CVE-2026-57585) | HIGH | `1.2.1` | `>=1.2.3` | Out-of-bounds read and crash when reusing an Unpacker instance after a caught error. Superset uses msgpack exclusively for SQL Lab asynchronous query result serialization (`RESULTS_BACKEND_USE_MSGPACK`); the Unpacker is never reused across error boundaries in production code paths. |
| **msgpack** | GHSA-j586-36cw-2gc2 | HIGH | `1.2.3` | `>=1.2.3` | Memory leak in the C extension when map key validation raises an exception during unpacking (triggers with default `strict_map_key=True` when a map key is not `str`/`bytes`). In Superset, msgpack deserialization via `msgpack.loads(payload, raw=False)` in `superset/views/utils.py` uses this default on cached query results from the results backend, whose provenance is internal Celery worker execution rather than direct user input. Operators should upgrade to `msgpack>=1.2.3` (Option A) to eliminate the leak path directly rather than relying on payload non-reachability. |
| **pyarrow** | CVE-2026-25087 | HIGH | `23.0.1` | `>=23.0.1` (core) / `>=26.0.0` (app) | Use-after-free in the Arrow C++ IPC file reader with pre-buffering (GHSA-rgxp-2hwp-jwgg). Superset invokes the Parquet reader for user data uploads and the IPC stream reader (`RecordBatchStreamReader`) for SQL Lab asynchronous query result serialization; it does not invoke the IPC file reader (`RecordBatchFileReader` with pre-buffering). Upstream fixes start at `23.0.1`, which is enforced as the minimum floor in `superset-core`, while root application requirements pin to `>=26.0.0`. |

## 2. Dependency Constraint Architecture

Apache Superset manages dependencies across two layers:

1. **Package Declarations (`pyproject.toml` and `superset-core/pyproject.toml`)**:
Specifies flexible semantic version ranges to avoid dependency resolver conflicts in downstream custom deployments.
- `cryptography` (`pyproject.toml`): `>=50.0.2, <51.0.0` (enforces remediated releases covering PKCS#7, path-building, certificate verification name constraints, and wheel OpenSSL advisories).
- `msgpack` (`pyproject.toml`): `>=1.2.3, <1.3` (enforces remediated releases covering both GHSA-6v7p-g79w-8964, fixed in 1.2.1, and GHSA-j586-36cw-2gc2, fixed in 1.2.3).
- `pyarrow`: Root `pyproject.toml` declares `>=26.0.0, <27` (pinned to `26.0.0` in `requirements/base.txt`); `superset-core/pyproject.toml` declares `>=23.0.1` (without an upper ceiling) to satisfy CVE-2026-25087 while permitting downstream extensions and application co-installation.

2. **Locked Requirements (`requirements/base.in` and `requirements/base.txt`)**:
Pins exact validated versions for official Docker images and deterministic continuous integration builds.

## 3. Operator Mitigations & Container Workarounds

If you are running an existing container image where dependency constraints prevent direct pip upgrades, the following approaches allow immediate remediation without breaking Superset:

### Option A: Extend Official Docker Image with Patched Dependencies

The official Docker image executes Superset inside a Python virtual environment located at `/app/.venv`. To ensure upgraded dependencies are installed directly into Superset runtime rather than the root container system packages, use `uv pip install --python /app/.venv/bin/python` (or `/app/.venv/bin/pip install` in environments without `uv`).

When upgrading `cryptography>=50.0.2`, `pyOpenSSL` must also be upgraded to `>=26.4.0` (matching the version pinned in `requirements/base.txt`). pyOpenSSL releases prior to 26.4.0 cap `cryptography` below 50 (with 25.x releases also attempting to access `_lib.GEN_EMAIL` when `OpenSSL.crypto` is imported, which is no longer exposed in cryptography 50.x). Upgrading pyOpenSSL to `>=26.4.0` alongside cryptography satisfies the dependency resolver and ensures imports of `OpenSSL` (used by Snowflake private key authentication and Google Cloud mutual TLS) succeed without error:

```dockerfile
FROM apache/superset:latest

USER root
RUN uv pip install --no-cache-dir --python /app/.venv/bin/python \
Comment thread
sadpandajoe marked this conversation as resolved.
Resolved
"cryptography>=50.0.2" \
"pyopenssl>=26.4.0" \
"msgpack>=1.2.3" \
"pyarrow>=26.0.0"

USER superset
```

### Option B: Scanner Triage and Ignore Rules (`.trivyignore`)

For organizations maintaining automated compliance gates, findings where the specific vulnerable code path is not reachable in the shipped Superset version and configuration can be documented and suppressed in `.trivyignore`. Note that Trivy matches suppression rules against the exact identifier reported by the scan engine; both CVE and GHSA aliases are provided below where applicable so rules match regardless of whether your feeds report under CVE or GitHub Advisory Database identifiers:

```text
# CVE-2026-69247: PKCS#7 EnvelopedData decryption is not used by Superset
CVE-2026-69247

# CVE-2026-69249: Untrusted X.509 certificate path-building is not exposed in request processing
CVE-2026-69249

# CVE-2026-69248: Cryptography X.509 certificate verifier APIs (cryptography.x509.verification) are not called by Superset
CVE-2026-69248

# Wheel-bundled OpenSSL in cryptography wheels (suppress only when system libssl is patched, or scope to pkg:pypi/cryptography):
CVE-2026-34180

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.trivyignore entries match by ID across every package, so CVE-2026-34180 also suppresses that finding for the system libssl in an image where only the Python wheels were upgraded via Option A (which doesn't change system OpenSSL). Copying this template could hide a reachable OpenSSL finding, not just the assessed wheel. Can the template scope this to the cryptography package (for example a purl-scoped ignore), or say it only applies once system OpenSSL is also patched?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in commit 11e2399.

The .trivyignore template has been updated to explicitly clarify that CVE-2026-34180 / GHSA-537c-gmf6-5ccf applies specifically to OpenSSL bundled in binary wheels (such as cryptography), with guidance to scope the rule using package-level ignore syntax (pkg:pypi/cryptography) or apply it only once system libssl packages are verified as patched, preventing unintentional suppression of host/container OS OpenSSL findings.

GHSA-537c-gmf6-5ccf
Comment thread
FrancescoCastaldi marked this conversation as resolved.
Resolved

# Msgpack Unpacker reuse after error: Unpacker instances are not reused across error boundaries
CVE-2026-57585
GHSA-6v7p-g79w-8964

# CVE-2026-25087 / GHSA-rgxp-2hwp-jwgg: Arrow C++ IPC file reader with pre-buffering is not invoked; Superset calls Parquet for uploads and IPC stream reader for SQL Lab results (remediated in pyarrow>=23.0.1 in core and >=26.0.0 in locked requirements)
CVE-2026-25087
Comment thread
sadpandajoe marked this conversation as resolved.
Resolved
GHSA-rgxp-2hwp-jwgg
```

:::note
`GHSA-j586-36cw-2gc2` is intentionally omitted from the `.trivyignore` template above. Because msgpack deserialization via `msgpack.loads(..., raw=False)` in `superset/views/utils.py` uses the default `strict_map_key=True` which can trigger the C extension memory leak on invalid map keys, operators running `msgpack==1.2.2` should remediate by upgrading to `msgpack>=1.2.3` (Option A) rather than suppressing the finding.
:::

## 4. Questions & Answers for Security Teams

**Q: Are these findings considered true vulnerabilities in Apache Superset?**
A: Per the Apache Superset Security Model (documented in `SECURITY.md`), vulnerabilities in shipped direct dependencies are kept in scope, which is why Superset directly bumps dependency floors to remediated releases. For operators managing legacy container images before upgrades are applied, the exploitability analysis in this guide documents the specific execution paths showing why unpatched intermediate environments are not exposed to remote code execution or authentication bypass.

**Q: Why are dependency bounds not completely unpinned?**
A: Database connectors and analytics engines (e.g., Snowflake, BigQuery, Trino, ClickHouse) impose mutual constraints on foundational packages like PyArrow and Cryptography. Version ranges are carefully calibrated to balance maximum security coverage with multi-database ecosystem stability.
9 changes: 7 additions & 2 deletions requirements/base.in
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,16 @@ filelock>=3.20.3,<4.0.0
# Security: decompression bomb fix (required by aiohttp 3.13.3); CVE-2026-111497
brotli>=1.2.1,<2.0.0
numexpr>=2.9.0
# Security: CVE-2026-34073 (MEDIUM) - Improper Certificate Validation
# Security: CVE-2026-34073 (MEDIUM) - Improper Certificate Validation;
# CVE-2026-69247, CVE-2026-69249, GHSA-537c-gmf6-5ccf, CVE-2026-69248 - certificate verification, path-building, and packaging advisories (#45087)
cryptography>=50.0.2,<51.0.0
# Security: GHSA-6v7p-g79w-8964 / CVE-2026-57585 (HIGH) - Out-of-bounds read/crash on Unpacker reuse;
# GHSA-j586-36cw-2gc2 (HIGH) - C extension memory leak on map key validation failure (#45087)
msgpack>=1.2.3,<1.3.0
# Security: Snyk - XSS vulnerability in Mako templates
mako>=1.4.3,<2.0.0
# Security: CVE-2024-52338 (CRITICAL) - Deserialization of untrusted data in IPC/Parquet readers
# Security: CVE-2024-52338 (CRITICAL) - Deserialization of untrusted data in IPC/Parquet readers;
# CVE-2026-25087 (HIGH) - Use-after-free in IPC file reader with pre-buffering (GHSA-rgxp-2hwp-jwgg) (#45087)
pyarrow>=26.0.0,<27.0.0
# Security: CVE-2026-27459 - pyopenssl certificate validation
pyopenssl>=26.0.0,<27.0.0
Expand Down
2 changes: 1 addition & 1 deletion superset-core/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ classifiers = [
dependencies = [
"flask-appbuilder>=5.2.0,<6",
"isodate>=0.7.0",
"pyarrow>=16.0.0",
"pyarrow>=23.0.1",
"pydantic>=2.8.0",
"sqlalchemy>=2.0.0,<2.1",
"sqlalchemy-utils>=0.38.0, <0.44", # expanding lowerbound to work with pydoris
Expand Down
11 changes: 8 additions & 3 deletions superset/db_engine_specs/snowflake.py
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,7 @@ def update_params_from_encrypted_extra(
logger.error(ex, exc_info=True)
raise
auth_method = encrypted_extra.get("auth_method", None)
auth_params = encrypted_extra.get("auth_params", {})
auth_params = encrypted_extra.get("auth_params") or {}
if not auth_method:
return
connect_args = params.setdefault("connect_args", {})
Expand All @@ -689,11 +689,16 @@ def update_params_from_encrypted_extra(
key = None
if privatekey_body:
key = privatekey_body.encode()
else:
elif auth_params.get("privatekey_path"):
Comment thread
sadpandajoe marked this conversation as resolved.
Resolved
with open(auth_params["privatekey_path"], "rb") as key_temp:
key = key_temp.read()
else:
raise ValueError(
"Either 'privatekey_body' or 'privatekey_path' must be provided "
"when using 'keypair' authentication"
)
privatekey_pass = auth_params.get("privatekey_pass", None)
password = privatekey_pass.encode() if privatekey_pass is not None else None
password = privatekey_pass.encode() if privatekey_pass else None
p_key = serialization.load_pem_private_key(
key,
password=password,
Expand Down
Loading
Loading