Skip to content

fix(dataset): apply the import overwrite permission check to identity-matched datasets - #43058

Open
sha174n wants to merge 1 commit into
apache:masterfrom
sha174n:fix/dataset-import-identity-access
Open

fix(dataset): apply the import overwrite permission check to identity-matched datasets#43058
sha174n wants to merge 1 commit into
apache:masterfrom
sha174n:fix/dataset-import-identity-access

Conversation

@sha174n

@sha174n sha174n commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

SqlaTable.import_from_dict matches an existing row on any of the model's unique constraints, which include (database_id, catalog, schema, table_name) as well as uuid. A dataset import whose config carried a fresh UUID but a physical identity already held by an active dataset was therefore matched and updated on that identity without passing through the overwrite permission gate, which only ran on a UUID match.

This resolves an active identity collision to the existing dataset before the gate runs (aligning the UUID so the subsequent import updates that row deterministically), so the same editor/admin overwrite check applies. Adds a regression test.

This mirrors the treatment already applied to the dashboard importer for slug collisions.

…-matched datasets

`SqlaTable.import_from_dict` matches an existing row on any of the model's
unique constraints, which include `(database_id, catalog, schema, table_name)`
as well as `uuid`. A dataset import whose config carried a fresh UUID but a
physical identity already held by an active dataset was therefore matched and
updated on that identity without passing through the overwrite permission gate,
which only ran on a UUID match.

Resolve an active identity collision to the existing dataset before the gate
runs (aligning the UUID so the subsequent import updates that row
deterministically), so the same editor/admin overwrite check applies. Adds a
regression test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@dosubot dosubot Bot added authentication:access-control Rlated to access control data:dataset Related to dataset configurations labels Aug 11, 2026
@bito-code-review

bito-code-review Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #d39f2f

Actionable Suggestions - 0
Review Details
  • Files reviewed - 2 · Commit Range: f216cc5..f216cc5
    • superset/commands/dataset/importers/v1/utils.py
    • tests/unit_tests/datasets/commands/importers/v1/import_test.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ 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

Comment on lines +261 to +269
active_twin = (
db.session.query(SqlaTable)
.filter_by(
database_id=config["database_id"],
catalog=config.get("catalog"),
schema=config.get("schema"),
table_name=config["table_name"],
)
.first()

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 active-twin probe uses a raw catalog=None equality, while import_from_dict omits nullable fields from its uniqueness predicate. If the incoming config has no catalog and the existing active dataset stores the database default catalog, this query misses the twin, but the later import lookup still matches it by database, schema, and table name. The import then updates the active dataset without reaching the overwrite permission check. Use the same null-aware/default-catalog identity predicate as the DAO or resolve the identity through the shared uniqueness helper. [security]

Severity Level: Critical 🚨
- ❌ Unauthorized imports can overwrite active datasets.
- ❌ Dataset SQL and metadata can be clobbered.
- ⚠️ Affects catalog-default database imports.

Fix in Cursor Fix in VSCode Claude

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

**Path:** superset/commands/dataset/importers/v1/utils.py
**Line:** 261:269
**Comment:**
	*Security: The active-twin probe uses a raw `catalog=None` equality, while `import_from_dict` omits nullable fields from its uniqueness predicate. If the incoming config has no catalog and the existing active dataset stores the database default catalog, this query misses the twin, but the later import lookup still matches it by database, schema, and table name. The import then updates the active dataset without reaching the overwrite permission check. Use the same null-aware/default-catalog identity predicate as the DAO or resolve the identity through the shared uniqueness helper.

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 on lines +272 to +273
config["uuid"] = str(active_twin.uuid)
existing = find_existing_for_import(SqlaTable, config["uuid"])

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 collision path rewrites the caller-owned config before the defensive copy later in the function. Consequently, callers retaining the uploaded configuration observe its fresh UUID replaced with the victim dataset's UUID; reusing or retrying that same dictionary can then address the victim by UUID and take a different overwrite path than the original import. Copy the input before resolving the collision, or keep the resolved UUID in a separate local import configuration. [stale reference]

Severity Level: Minor 🧹
- ⚠️ Reused import configs retain the victim UUID.
- ⚠️ Retries can select different UUID-based branches.
- ⚠️ Affects callers retaining bundle configuration dictionaries.

Fix in Cursor Fix in VSCode Claude

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

**Path:** superset/commands/dataset/importers/v1/utils.py
**Line:** 272:273
**Comment:**
	*Stale Reference: The collision path rewrites the caller-owned `config` before the defensive copy later in the function. Consequently, callers retaining the uploaded configuration observe its fresh UUID replaced with the victim dataset's UUID; reusing or retrying that same dictionary can then address the victim by UUID and take a different overwrite path than the original import. Copy the input before resolving the collision, or keep the resolved UUID in a separate local import configuration.

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 Aug 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 57.14286% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.54%. Comparing base (5ee2793) to head (f216cc5).

Files with missing lines Patch % Lines
superset/commands/dataset/importers/v1/utils.py 57.14% 2 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #43058      +/-   ##
==========================================
- Coverage   66.55%   66.54%   -0.01%     
==========================================
  Files        2864     2864              
  Lines      161894   161900       +6     
  Branches    37305    37307       +2     
==========================================
  Hits       107742   107742              
- Misses      52106    52110       +4     
- Partials     2046     2048       +2     
Flag Coverage Δ
hive 38.15% <0.00%> (-0.01%) ⬇️
mysql 57.68% <57.14%> (-0.01%) ⬇️
postgres 57.73% <57.14%> (-0.01%) ⬇️
presto 40.11% <0.00%> (-0.01%) ⬇️
python 59.11% <57.14%> (-0.01%) ⬇️
sqlite 57.35% <57.14%> (-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.

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

Labels

authentication:access-control Rlated to access control data:dataset Related to dataset configurations size/M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant