Compare commits

...

2 Commits

Author SHA1 Message Date
Evan
30f9a8d8e1 fix(config): redact full_sha and add return type hints
- Drop full_sha in visible_version_metadata when build details are hidden
- Add explicit return type annotations to version_test helpers/tests

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 21:06:27 -07:00
Amin Ghadersohi
3c92e56b8c fix(config): expose build details (git SHA/build number) to admins only
VERSION_SHA and BUILD_NUMBER were included in the "About" section and the
bootstrap payload for all viewers, letting anyone able to load the page map the
deployment to an exact commit/build. Gate these precise build details behind a
new EXPOSE_BUILD_DETAILS_TO_USERS config (env: SUPERSET_EXPOSE_BUILD_DETAILS,
default off): they are included only for admins unless the deployment opts in.
The release version string is still shown to everyone.

Adds a pure visible_version_metadata() helper with unit tests and documents the
change in UPDATING.md.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-22 17:43:05 -07:00
5 changed files with 100 additions and 3 deletions

View File

@@ -24,6 +24,10 @@ assists people when migrating to a new version.
## Next
### Build details (git SHA / build number) are admin-only by default
The git SHA and build number surfaced in the "About" section and the bootstrap payload are now only included for admin users by default; the release version string is still shown to everyone. To expose the build details to all users (the previous behavior), set the `SUPERSET_EXPOSE_BUILD_DETAILS` environment variable (or `EXPOSE_BUILD_DETAILS_TO_USERS = True` in `superset_config.py`).
### Pivot table First/Last aggregations follow data order
The pivot table chart's `First` and `Last` aggregations now return the first and last value in data (query result) order, instead of effectively returning the minimum and maximum. Existing pivot tables that use these aggregations for totals/subtotals may show different values after upgrading. For deterministic results, ensure the underlying query has a stable sort order.

View File

@@ -160,6 +160,15 @@ VERSION_SHA = _try_json_readsha(VERSION_INFO_FILE, VERSION_SHA_LENGTH)
# can be replaced at build time to expose build information.
BUILD_NUMBER = None
# Whether to expose precise build details (the git SHA and build number) to
# all users via the "About" section and the bootstrap payload. When False
# (default), these are only included for admins, so non-admin/anonymous viewers
# cannot read the exact commit/build of the deployment. The release version
# string is always included. Enable with SUPERSET_EXPOSE_BUILD_DETAILS.
EXPOSE_BUILD_DETAILS_TO_USERS = utils.cast_to_boolean(
os.environ.get("SUPERSET_EXPOSE_BUILD_DETAILS", False)
)
# default viz used in chart explorer & SQL Lab explore
DEFAULT_VIZ_TYPE = "table"

View File

@@ -57,6 +57,23 @@ def get_version_metadata() -> dict[str, Any]:
return metadata
def visible_version_metadata(
metadata: dict[str, Any], expose_build_details: bool
) -> dict[str, Any]:
"""Return version metadata for user-facing surfaces.
The release ``version_string`` is always included. Precise build details
(the git SHAs and build number), which let a viewer map the deployment to a
specific commit/build, are blanked out unless ``expose_build_details`` is
True (e.g. the viewer is an admin or the deployment opted in).
"""
if expose_build_details:
return metadata
redacted = {**metadata, "version_sha": "", "build_number": None}
redacted.pop("full_sha", None)
return redacted
def get_dev_env_label() -> str:
"""
Generate development environment label with branch/SHA info.

View File

@@ -66,7 +66,7 @@ from superset.themes.utils import (
)
from superset.utils import core as utils, json
from superset.utils.filters import get_dataset_access_filters
from superset.utils.version import get_version_metadata
from superset.utils.version import get_version_metadata, visible_version_metadata
from superset.views.error_handling import json_error_response
from .utils import bootstrap_user_data, get_config_value
@@ -279,8 +279,16 @@ def menu_data(user: User) -> dict[str, Any]:
if callable(brand_text := app.config["LOGO_RIGHT_TEXT"]):
brand_text = brand_text()
# Get centralized version metadata
version_metadata = get_version_metadata()
# Get centralized version metadata. Precise build details (git SHA and
# build number) let a viewer map the deployment to a specific commit/build,
# so expose them only to admins unless the deployment opts in via
# EXPOSE_BUILD_DETAILS_TO_USERS. The release version string is always shown.
expose_build_details = (
app.config["EXPOSE_BUILD_DETAILS_TO_USERS"] or security_manager.is_admin()
)
version_metadata = visible_version_metadata(
get_version_metadata(), expose_build_details
)
return {
"menu": appbuilder.menu.get_data(),

View File

@@ -0,0 +1,59 @@
# 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.
"""Tests for superset.utils.version helpers."""
from typing import Any
from superset.utils.version import visible_version_metadata
def _metadata() -> dict[str, Any]:
return {
"version_string": "4.0.0",
"version_sha": "abcdef12",
"build_number": "build-42",
}
def test_visible_version_metadata_hides_build_details_when_not_exposed() -> None:
"""Build details are blanked while the release version string is kept."""
result = visible_version_metadata(_metadata(), expose_build_details=False)
assert result["version_string"] == "4.0.0"
assert result["version_sha"] == ""
assert result["build_number"] is None
def test_visible_version_metadata_drops_full_sha_when_not_exposed() -> None:
"""The exact commit SHA must not survive redaction."""
metadata = {**_metadata(), "full_sha": "abcdef1234567890"}
result = visible_version_metadata(metadata, expose_build_details=False)
assert "full_sha" not in result
def test_visible_version_metadata_keeps_build_details_when_exposed() -> None:
"""All details pass through unchanged when exposure is allowed."""
metadata = _metadata()
result = visible_version_metadata(metadata, expose_build_details=True)
assert result == metadata
def test_visible_version_metadata_does_not_mutate_input() -> None:
"""Hiding build details must not mutate the caller's metadata dict."""
metadata = _metadata()
visible_version_metadata(metadata, expose_build_details=False)
assert metadata["version_sha"] == "abcdef12"
assert metadata["build_number"] == "build-42"