Skip to content

fix(config): expose build details (git SHA/build number) to admins only#41301

Open
rusackas wants to merge 1 commit into
masterfrom
fix/expose-build-details-opt-in
Open

fix(config): expose build details (git SHA/build number) to admins only#41301
rusackas wants to merge 1 commit into
masterfrom
fix/expose-build-details-opt-in

Conversation

@rusackas

Copy link
Copy Markdown
Member

SUMMARY

VERSION_SHA and BUILD_NUMBER were surfaced in the frontend "About" section and the common bootstrap payload for every viewer, disclosing the precise git commit and build of the deployment (useful reconnaissance for mapping to known issues for an exact build).

This gates those precise build details behind a new EXPOSE_BUILD_DETAILS_TO_USERS config (env: SUPERSET_EXPOSE_BUILD_DETAILS, default off). The git SHA and build number are included only for admin users unless a deployment opts in. The release version_string is still shown to everyone (it is widely used in the UI/About).

A small pure helper visible_version_metadata() encapsulates the gating so it is easy to test.

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

N/A — bootstrap payload contents.

TESTING INSTRUCTIONS

Unit tests added in tests/unit_tests/utils/version_test.py:

  • When not exposed, version_sha/build_number are blanked while version_string is kept.
  • When exposed, all details pass through.
  • The input dict is not mutated.

Run: pytest tests/unit_tests/utils/version_test.py

Manual: as a non-admin, the bootstrap payload navbar_right.version_sha is empty and build_number is null; as an admin (or with SUPERSET_EXPOSE_BUILD_DETAILS=true) they are populated.

ADDITIONAL INFORMATION

  • Has associated issue:
  • Required feature flags:
  • Changes UI
  • Includes DB Migration (follow approval process in SIP-59)
    • Migration is atomic, supports rollback & is backwards-compatible
    • Confirm DB migration upgrade and downgrade tested
    • Runtime estimates and downtime expectations provided
  • Introduces new feature or API
  • Removes existing feature or API

Note: changes default visibility of build details (admin-only by default); documented in UPDATING.md.

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>
@rusackas rusackas added the asvs label Jun 23, 2026
@dosubot dosubot Bot added authentication:RBAC Related to RBAC install:config Installation - Configuration settings labels Jun 23, 2026
@bito-code-review

bito-code-review Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #6a880d

Actionable Suggestions - 0
Review Details
  • Files reviewed - 4 · Commit Range: 3c92e56..3c92e56
    • superset/config.py
    • superset/utils/version.py
    • superset/views/base.py
    • tests/unit_tests/utils/version_test.py
  • Files skipped - 1
    • UPDATING.md - Reason: Filter setting
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

from superset.utils.version import visible_version_metadata


def _metadata():

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggestion: Add an explicit return type annotation to this helper function so the newly added code is fully typed. [custom_rule]

Severity Level: Minor ⚠️

Why it matters? 🤔

The file is newly added Python code, and this helper function has no type hints for its return value. That matches the rule requiring newly added Python functions to be fully typed.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** tests/unit_tests/utils/version_test.py
**Line:** 22:22
**Comment:**
	*Custom Rule: Add an explicit return type annotation to this helper function so the newly added code is fully typed.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

}


def test_visible_version_metadata_hides_build_details_when_not_exposed():

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggestion: Add a -> None return annotation to this new test function to satisfy full typing requirements for added Python functions. [custom_rule]

Severity Level: Minor ⚠️

Why it matters? 🤔

The function is newly added Python code and it lacks a return type annotation. That is a real violation of the full-typing rule for new functions.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** tests/unit_tests/utils/version_test.py
**Line:** 30:30
**Comment:**
	*Custom Rule: Add a `-> None` return annotation to this new test function to satisfy full typing requirements for added Python functions.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

assert result["build_number"] is None


def test_visible_version_metadata_keeps_build_details_when_exposed():

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggestion: Add a -> None return annotation to this new test function so the added code includes complete type hints. [custom_rule]

Severity Level: Minor ⚠️

Why it matters? 🤔

This newly added test function has no return type annotation, which violates the rule that new Python functions should be fully typed.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** tests/unit_tests/utils/version_test.py
**Line:** 38:38
**Comment:**
	*Custom Rule: Add a `-> None` return annotation to this new test function so the added code includes complete type hints.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

assert result == metadata


def test_visible_version_metadata_does_not_mutate_input():

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggestion: Add a -> None return annotation to this new test function to align with the rule requiring full typing in newly changed code. [custom_rule]

Severity Level: Minor ⚠️

Why it matters? 🤔

This newly introduced test function also lacks a return type annotation, so it fits the typing rule violation.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** tests/unit_tests/utils/version_test.py
**Line:** 45:45
**Comment:**
	*Custom Rule: Add a `-> None` return annotation to this new test function to align with the rule requiring full typing in newly changed code.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

@codecov

codecov Bot commented Jun 23, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 64.34%. Comparing base (3b46a5f) to head (3c92e56).

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #41301      +/-   ##
==========================================
- Coverage   64.34%   64.34%   -0.01%     
==========================================
  Files        2653     2653              
  Lines      144952   144958       +6     
  Branches    33433    33434       +1     
==========================================
+ Hits        93273    93274       +1     
- Misses      49995    49998       +3     
- Partials     1684     1686       +2     
Flag Coverage Δ
hive 39.28% <100.00%> (+<0.01%) ⬆️
mysql 58.00% <100.00%> (+<0.01%) ⬆️
postgres 58.07% <100.00%> (-0.01%) ⬇️
presto 40.87% <100.00%> (+<0.01%) ⬆️
python 59.51% <100.00%> (-0.01%) ⬇️
sqlite 57.72% <100.00%> (+<0.01%) ⬆️
unit 100.00% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread superset/utils/version.py
"""
if expose_build_details:
return metadata
return {**metadata, "version_sha": "", "build_number": None}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggestion: The redaction helper does not remove full_sha, even though that field is an exact git commit identifier and is part of the metadata produced upstream. With expose_build_details=False, callers that serialize this returned dict can still leak precise build identity. Redact/remove full_sha together with the short SHA/build number. [security]

Severity Level: Major ⚠️
- ⚠️ Redaction helper leaves full_sha populated when hiding details.
- ⚠️ Future serializers may expose exact commit SHA to users.
Steps of Reproduction ✅
1. Configure Superset with `EXPOSE_BUILD_DETAILS_TO_USERS = False` in
`superset/config.py:54-61` and run the server in an environment where `GITHUB_SHA` is set
(e.g. CI-built container), so `get_version_metadata()` will populate `full_sha`.

2. Trigger any code path that calls `menu_data(user)`; for example, a SPA page render via
`SupersetModelView.render_app_template()` in `superset/views/base.py:670-672`, which calls
`get_spa_template_context()` (`base.py:583-587`), then `common_bootstrap_payload()`
(`base.py:38-42`), then `cached_common_bootstrap_data()` (`base.py:452-456`), which builds
`"menu_data": menu_data(g.user)` at `base.py:528-528`.

3. Inside `menu_data()` (`superset/views/base.py:273-291`), `version_metadata =
visible_version_metadata(get_version_metadata(), expose_build_details)` is executed
(`base.py:289-291`). `get_version_metadata()` from `superset/utils/version.py:29-57` reads
`GITHUB_SHA` and sets `metadata["full_sha"] = github_sha` at `version.py:44`.

4. Because `expose_build_details` is False for a non-admin user,
`visible_version_metadata()` in `superset/utils/version.py:60-72` returns `{**metadata,
"version_sha": "", "build_number": None}` (`version.py:72`), leaving
`metadata["full_sha"]` untouched. Inspecting `version_metadata` in a debugger or via
temporary logging confirms that `version_metadata["full_sha"]` still contains the exact
commit SHA even though build details are supposed to be hidden, so any caller that later
serializes the whole dict (instead of selecting keys as `menu_data` currently does) would
leak the full commit identifier.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** superset/utils/version.py
**Line:** 72:72
**Comment:**
	*Security: The redaction helper does not remove `full_sha`, even though that field is an exact git commit identifier and is part of the metadata produced upstream. With `expose_build_details=False`, callers that serialize this returned dict can still leak precise build identity. Redact/remove `full_sha` together with the short SHA/build number.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

Comment thread superset/views/base.py
Comment on lines +289 to +291
version_metadata = visible_version_metadata(
get_version_metadata(), expose_build_details
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggestion: menu_data now calls get_version_metadata() on the bootstrap path, and that helper can run git rev-parse subprocess calls when CI env vars are not present. Since this code is reached for normal page bootstrap traffic, it introduces avoidable per-request process-spawn overhead (memoized only for 60s per user/locale). Use already-loaded config values for navbar version fields or memoize version metadata independently of request/user context. [performance]

Severity Level: Major ⚠️
- ⚠️ spa.html bootstrap path runs git subprocess on cache misses.
- ⚠️ Superset UI requests incur extra CPU and process overhead.
Steps of Reproduction ✅
1. Run Superset in an environment where `GITHUB_HEAD_REF` and `GITHUB_REF_NAME` are unset
(typical non-CI deployment) so `get_version_metadata()` must fall back to
`_get_local_branch()`; confirm no branch env vars are set.

2. From a browser, load any SPA page rendered via
`SupersetModelView.render_app_template()` in `superset/views/base.py:670-672`, which calls
`get_spa_template_context()` (`base.py:583-587`), then `common_bootstrap_payload()`
(`base.py:38-42`), which in turn calls `cached_common_bootstrap_data(utils.get_user_id(),
locale_str)` at `base.py:42`.

3. On a cache miss for `cached_common_bootstrap_data` (per
`@cache_manager.cache.memoize(timeout=60)` at `superset/views/base.py:452-456`), the
function constructs the bootstrap dict including `"menu_data": menu_data(g.user)` at
`base.py:528-528`. Inside `menu_data()` (`base.py:273-291`), it computes `version_metadata
= visible_version_metadata(get_version_metadata(), expose_build_details)` at
`base.py:289-291`.

4. `get_version_metadata()` (`superset/utils/version.py:29-57`) calls
`_get_local_branch()` at `version.py:48-53`, which executes
`subprocess.check_output(["git", "rev-parse", "--abbrev-ref", "HEAD"], ...)` in
`_get_local_branch()` (`version.py:106-115`). Profiling or adding temporary logging around
`_get_local_branch()` shows a `git rev-parse` subprocess being spawned on each cache miss
(i.e., at least once every 60 seconds per user/locale) along this common bootstrap path.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** superset/views/base.py
**Line:** 289:291
**Comment:**
	*Performance: `menu_data` now calls `get_version_metadata()` on the bootstrap path, and that helper can run `git rev-parse` subprocess calls when CI env vars are not present. Since this code is reached for normal page bootstrap traffic, it introduces avoidable per-request process-spawn overhead (memoized only for 60s per user/locale). Use already-loaded config values for navbar version fields or memoize version metadata independently of request/user context.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

asvs authentication:RBAC Related to RBAC install:config Installation - Configuration settings size/M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants