FrancescoCastaldi commented on code in PR #45186:
URL: https://github.com/apache/superset/pull/45186#discussion_r4241938035
##########
pyproject.toml:
##########
@@ -82,7 +82,7 @@ dependencies = [
# https://github.com/apache/superset/issues/33162
"marshmallow>=3.0, <5",
"marshmallow-union>=0.1.15.post1",
- "msgpack>=1.2.3, <1.3",
+ "msgpack>=1.2.1, <1.3",
Review Comment:
Agreed. Restored the msgpack floor to >=1.2.3, <1.3 in pyproject.toml and
updated the security test matrix to explicitly test and reject msgpack 1.2.1
and 1.2.2 to prevent GHSA-j586-36cw-2gc2, as implemented in commit 0ec4b68102.
##########
superset/utils/core.py:
##########
@@ -1658,7 +1658,11 @@ def parse_ssl_cert(certificate: str) -> Certificate:
:raises CertificateException: If certificate is not valid/unparseable
"""
try:
- return load_pem_x509_certificate(certificate.encode("utf-8"),
default_backend())
+ data = certificate.encode("utf-8")
+ try:
+ return load_pem_x509_certificate(data)
Review Comment:
Added unit tests
test_parse_ssl_cert_type_error_fallback_with_default_backend and
test_parse_ssl_cert_fallback_value_error_becomes_certificate_exception in
tests/unit_tests/utils/test_core.py, verifying the retry with default_backend()
when load_pem_x509_certificate raises TypeError, as implemented in commit
0ec4b68102.
##########
scripts/check_security_dependencies.py:
##########
@@ -0,0 +1,208 @@
+#!/usr/bin/env python3
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""
+CI/CD verification script: audit security dependency constraints.
+Ensures that pyproject.toml, superset-core/pyproject.toml, and
requirements/base.in
+satisfy CVE remediation floors and reject known vulnerable versions (issue
#45087).
+"""
+
+import sys
+from pathlib import Path
+
+from packaging.requirements import Requirement
+from packaging.version import Version
+
+ROOT_DIR = Path(__file__).resolve().parents[1]
+
+# Known vulnerable versions from Trivy/Snyk scans that must NOT be accepted
+VULNERABLE_TEST_MATRIX = {
+ "cryptography": [
+ ("46.0.7", "CVE-2026-69247 / CVE-2026-69249 / GHSA-537c-gmf6-5ccf"),
+ ("47.0.0", "CVE-2026-69247 / CVE-2026-69249"),
+ ("48.0.0", "CVE-2026-69247 / GHSA-537c-gmf6-5ccf"),
+ ],
+ "msgpack": [
+ ("1.0.8", "GHSA-6v7p-g79w-8964"),
+ ("1.1.0", "GHSA-6v7p-g79w-8964"),
+ ("1.2.0", "GHSA-6v7p-g79w-8964"),
+ ],
+ "pyarrow": [
+ ("16.1.0", "CVE-2026-25087 / CVE-2024-52338"),
+ ("18.0.0", "CVE-2026-25087"),
+ ("22.0.0", "CVE-2026-25087"),
+ ],
+}
+
+# Remediation versions that MUST be accepted
+REMEDIATED_TEST_MATRIX = {
+ "cryptography": ["48.0.1", "49.0.0", "50.0.0", "50.0.2"],
+ "msgpack": ["1.2.1", "1.2.3"],
+ "pyarrow": ["25.0.1"],
+}
+
+
+def parse_pyproject_deps(path: Path) -> dict[str, Requirement]:
+ """Extract dependencies from pyproject.toml."""
+ content = path.read_text(encoding="utf-8")
+ reqs: dict[str, Requirement] = {}
+ in_deps = False
+
+ for line in content.splitlines():
+ stripped = line.strip()
+ if stripped == "dependencies = [":
+ in_deps = True
+ continue
+ if in_deps:
+ if stripped == "]":
+ break
+ if "#" in stripped:
+ stripped = stripped.split("#", 1)[0].strip()
+ stripped = stripped.rstrip(",")
+ if (stripped.startswith('"') and stripped.endswith('"')) or (
+ stripped.startswith("'") and stripped.endswith("'")
+ ):
+ stripped = stripped[1:-1].strip()
+ if stripped:
+ req = Requirement(stripped)
+ reqs[req.name.lower()] = req
+
+ return reqs
+
+
+def _audit_root_package(
+ root_deps: dict[str, Requirement],
+ errors: list[str],
+) -> None:
+ """Audit root pyproject.toml dependencies against vulnerable/remediated
matrix."""
+ for pkg_name, vulnerable_cases in VULNERABLE_TEST_MATRIX.items():
+ if pkg_name not in root_deps:
+ errors.append(f"Missing '{pkg_name}' in root pyproject.toml")
+ continue
+
+ spec = root_deps[pkg_name].specifier
+ print(f" - {pkg_name}: declared constraint '{spec}'")
+
+ for ver_str, cve_info in vulnerable_cases:
+ v = Version(ver_str)
+ if v in spec:
+ msg = (
+ f"Root permits vulnerable {pkg_name}=={ver_str} "
+ f"({cve_info}) under '{spec}'"
+ )
+ errors.append(msg)
+ else:
+ print(f" [OK] Rejects vulnerable {pkg_name} {ver_str}")
+
+ for ver_str in REMEDIATED_TEST_MATRIX[pkg_name]:
+ v = Version(ver_str)
+ if v not in spec:
+ msg = (
+ f"Root erroneously blocks remediated {pkg_name}=={ver_str}
"
+ f"under '{spec}'"
+ )
+ errors.append(msg)
+ else:
+ print(f" [OK] Accepts remediated {pkg_name} {ver_str}")
+
+
+def _audit_core_subpackage(
+ core_deps: dict[str, Requirement],
+ errors: list[str],
+) -> None:
+ """Audit superset-core/pyproject.toml pyarrow dependency."""
+ if "pyarrow" not in core_deps:
+ errors.append("Missing 'pyarrow' in superset-core/pyproject.toml")
+ return
+
+ core_spec = core_deps["pyarrow"].specifier
+ print(f" - pyarrow: declared constraint '{core_spec}'")
+ for ver_str, cve_info in VULNERABLE_TEST_MATRIX["pyarrow"]:
+ v = Version(ver_str)
+ if v in core_spec:
+ msg = (
+ f"superset-core permits vulnerable pyarrow=={ver_str} "
+ f"({cve_info}) under '{core_spec}'"
+ )
+ errors.append(msg)
+ else:
+ print(f" [OK] Rejects vulnerable pyarrow {ver_str}
({cve_info})")
+
+
+def _audit_base_requirements(
+ base_in_content: str,
+ base_in_path: Path,
+ errors: list[str],
+) -> None:
+ """Audit requirements/base.in for required annotations and floors."""
+ required_markers = [
+ ("msgpack", "msgpack declaration"),
+ ("GHSA-6v7p-g79w-8964", "msgpack CVE annotation"),
+ ("CVE-2026-69247", "cryptography CVE annotation"),
+ ("CVE-2026-25087", "pyarrow CVE annotation"),
+ ]
+
+ for marker, description in required_markers:
Review Comment:
Updated scripts/check_security_dependencies.py to extract and parse active
requirement lines from requirements/base.in and validate their specifiers
against both the vulnerable and remediated test matrices, rather than scanning
comment strings, as implemented in commit 0ec4b68102.
##########
tests/unit_tests/security/test_dependency_conflicts_reproduction.py:
##########
@@ -0,0 +1,85 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+"""
+Regression test for issue #45087 reproduction:
+Verifies that container security scanner recommendations (cryptography 50.0.2,
+msgpack 1.2.3, pyarrow 25.0.1) can be satisfied simultaneously by Superset
+without dependency resolver conflicts.
+"""
+
+from pathlib import Path
+
+from packaging.requirements import Requirement
+from packaging.version import Version
+
+ROOT_DIR = Path(__file__).resolve().parents[3]
+
+
+def test_trivy_remediation_versions_resolve_without_conflict() -> None:
+ """
+ Simulate pip dependency resolution for the scanner-reported remediation
versions.
+ Validates that:
+ 1. cryptography 50.0.2 satisfies root constraints.
+ 2. msgpack 1.2.3 satisfies root constraints.
+ 3. pyarrow 25.0.1 satisfies both root and superset-core constraints.
+ """
+ root_pyproject = (ROOT_DIR / "pyproject.toml").read_text(encoding="utf-8")
+ core_pyproject_path = ROOT_DIR / "superset-core" / "pyproject.toml"
+ core_pyproject = core_pyproject_path.read_text(encoding="utf-8")
+
+ def get_req(content: str, name: str) -> Requirement:
+ for line in content.splitlines():
+ stripped = line.strip()
+ if "#" in stripped:
+ stripped = stripped.split("#", 1)[0].strip()
+ stripped = stripped.rstrip(",")
+ if (stripped.startswith('"') and stripped.endswith('"')) or (
+ stripped.startswith("'") and stripped.endswith("'")
+ ):
+ stripped = stripped[1:-1].strip()
+ if stripped.lower().startswith(name.lower()):
+ return Requirement(stripped)
+ raise ValueError(f"Requirement '{name}' not found")
+
+ root_crypto = get_req(root_pyproject, "cryptography")
+ root_msgpack = get_req(root_pyproject, "msgpack")
+ root_pyarrow = get_req(root_pyproject, "pyarrow")
+ core_pyarrow = get_req(core_pyproject, "pyarrow")
+
+ # Target versions recommended by Trivy scanner
+ trivy_crypto_version = Version("50.0.2")
+ trivy_msgpack_version = Version("1.2.3")
+ trivy_pyarrow_version = Version("25.0.1")
+
+ # Assert all target versions satisfy the respective specifiers
+ assert trivy_crypto_version in root_crypto.specifier, (
Review Comment:
Updated test_dependency_conflicts_reproduction.py to also assert that
vulnerable versions reported by container scanners (cryptography 50.0.1,
msgpack 1.2.2, pyarrow 23.0.1) are strictly rejected by the new package floors,
as implemented in commit 0ec4b68102.
##########
docs/admin_docs/security/dependency-vulnerability-remediation.mdx:
##########
@@ -0,0 +1,77 @@
+---
+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 | Remediation Floor | Superset Code Path &
Exploitability Analysis |
+| :--- | :--- | :--- | :--- | :--- |
+| **cryptography** | CVE-2026-69247, CVE-2026-69249, GHSA-537c-gmf6-5ccf,
CVE-2026-69248 | HIGH / MEDIUM | `>=48.0.1` (resolved in `50.0.2`) | Used
primarily for encrypting database connection passwords at rest and parsing
operator-supplied SSL certificates. Unauthenticated external input does not
traverse PKCS12 parsing routines. Exploitability in standard deployments is
considered low. |
+| **msgpack** | GHSA-6v7p-g79w-8964 | HIGH | `>=1.2.1` (resolved in `1.2.3`) |
Utilized internally for SQL Lab asynchronous query result serialization
(`RESULTS_BACKEND_USE_MSGPACK`). Raw msgpack byte streams are generated and
consumed only within the trusted backend cache boundary. Exploitability
requires full cache store compromise. |
+| **pyarrow** | CVE-2026-25087 | HIGH | `>=23.0.1` (resolved in `25.0.1`) |
Used for columnar tabular transformations and CSV/Parquet ingestion by
authenticated users. Ingestion pathways are governed by role-based permissions
and file size limits. Exploitability is bounded to authorized data uploads. |
+
+## 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`: `>=48.0.1, <51.0.0` (accepts all remediated releases from
48.0.1 through 50.x while barring vulnerable <48.0.1 versions).
+ - `msgpack`: `>=1.2.1, <1.3` (accepts all remediated releases from 1.2.1
through 1.2.x while barring vulnerable <1.2.1 versions).
+ - `pyarrow`: `>=25.0.1, <26` (enforces modern non-vulnerable engines in
both core and main packages).
+
+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
+
+Create a customized Dockerfile that layers the fixed libraries on top of the
base image:
+
+```dockerfile
+FROM apache/superset:latest
+
+USER root
+RUN pip install --no-cache-dir \
Review Comment:
Updated the Dockerfile snippet in the remediation guide to use uv pip
install --no-cache-dir --python /app/.venv/bin/python, ensuring patched
packages are installed directly into Superset virtual environment, as
implemented in commit 0ec4b68102.
--
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]