You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@superset.apache.org by "rusackas (via GitHub)" <gi...@apache.org> on 2026/09/08 15:19:34 UTC
[PR] fix(database): don't reattach stored connection secrets when the effective destination changes [superset]
rusackas opened a new pull request, #44003:
URL: https://github.com/apache/superset/pull/44003
### SUMMARY
`test_connection`, `validate_parameters`, database update, and database import all decide whether to reattach a stored connection secret (password, `encrypted_extra`, or SSH tunnel credential) by comparing one visible field against its masked/stored form, without checking whether other request-controlled fields also feed into the actual connection destination.
`extra.engine_params` (in particular `engine_params.connect_args.host`/`.port`) is merged into the DBAPI connect kwargs by SQLAlchemy and can override the host/port carried in the URI itself. The SSH tunnel's `server_address`/`server_port` can change independently of the URI. For database update, the URI's own host/port can change directly while its password segment stays masked, with nothing comparing it against the stored host first.
This PR adds an identity check across all four paths (mirroring the check #43393 already added for database import's URI-host case, extended to also cover `extra.engine_params`, and applied fresh to database update, which had none before) and refuses to reattach a stored secret unless a fresh credential is supplied for a destination that changed. Shared comparison logic lives in `superset/commands/database/utils.py`. Also scopes `DatabaseDAO.get_database_by_name` to the same `DatabaseFilter` object-visibility boundary `find_by_id`/`get_connection` already use for this resource.
### BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
N/A โ backend-only change, no UI impact.
### TESTING INSTRUCTIONS
Regression tests added per site (`extra.engine_params` variant, SSH-tunnel-endpoint variant, and for database update also the plain URI-host variant). Each was verified to fail without its corresponding fix and pass with it. `pytest tests/unit_tests/commands/databases/ tests/unit_tests/databases/ tests/unit_tests/daos/` โ 521 passed. Legitimate flows (unchanged destination, or a deliberate move with a freshly supplied credential) are covered and unaffected.
### ADDITIONAL INFORMATION
- [ ] Has associated issue
- [ ] Required feature flags
- [ ] Changes UI
- [ ] Includes DB Migration (follow approval process in [SIP-59](https://github.com/apache/superset/issues/13351))
- [ ] Confirm DB Migration upgrade and downgrade tested
- [ ] Introduces new feature or API
- [ ] Removes existing feature or API
--
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: notifications-unsubscribe@superset.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org
Re: [PR] fix(database): don't reattach stored connection details when the effective destination changes [superset]
Posted by "bito-code-review[bot] (via GitHub)" <gi...@apache.org>.
bito-code-review[bot] commented on PR #44003:
URL: https://github.com/apache/superset/pull/44003#issuecomment-5587602337
<!-- Bito Reply -->
The flagged issue is correct. The current implementation of `_check_no_unsafe_secret_rebind` in `superset/commands/database/update.py` only checks for `PASSWORD_MASK` or `None` in the `sqlalchemy_uri` password field when a destination change is detected. It fails to account for cases where the password might be stored in `encrypted_extra` (which is common for engines that store authentication outside the URI).
To resolve this, you should update the check to also verify if `encrypted_extra` is being reused (i.e., remains masked) when a destination change occurs.
Would you like me to fetch all other comments on this PR to validate and implement fixes for them as well?
**superset/commands/database/update.py**
```
if connection_identity_changed and (
submitted_password in (None, PASSWORD_MASK)
or self._properties.get("encrypted_extra") == PASSWORD_MASK
):
raise DatabaseInvalidError(exceptions=[DatabaseUpdateUnsafeRebindError()])
```
--
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: notifications-unsubscribe@superset.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org
Re: [PR] fix(database): don't reattach stored connection secrets when the effective destination changes [superset]
Posted by "bito-code-review[bot] (via GitHub)" <gi...@apache.org>.
bito-code-review[bot] commented on PR #44003:
URL: https://github.com/apache/superset/pull/44003#issuecomment-5587511066
AI Code Review is in progress (usually takes 3 to 15 minutes unless it's a very large PR).
--
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: notifications-unsubscribe@superset.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org
Re: [PR] fix(database): don't reattach stored connection details when the effective destination changes [superset]
Posted by "codecov[bot] (via GitHub)" <gi...@apache.org>.
codecov[bot] commented on PR #44003:
URL: https://github.com/apache/superset/pull/44003#issuecomment-5587655953
## [Codecov](https://app.codecov.io/gh/apache/superset/pull/44003?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) Report
:x: Patch coverage is `25.27473%` with `68 lines` in your changes missing coverage. Please review.
:white_check_mark: Project coverage is 57.53%. Comparing base ([`c4e145b`](https://app.codecov.io/gh/apache/superset/commit/c4e145b071f8ec708ca16485852de3dd8bec9117?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)) to head ([`87a5280`](https://app.codecov.io/gh/apache/superset/commit/87a528051229e7751af99c726d595efab3a62aa6?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)).
:warning: Report is 1 commits behind head on master.
| [Files with missing lines](https://app.codecov.io/gh/apache/superset/pull/44003?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | Patch % | Lines |
|---|---|---|
| [superset/commands/database/utils.py](https://app.codecov.io/gh/apache/superset/pull/44003?src=pr&el=tree&filepath=superset%2Fcommands%2Fdatabase%2Futils.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-c3VwZXJzZXQvY29tbWFuZHMvZGF0YWJhc2UvdXRpbHMucHk=) | 31.25% | [22 Missing :warning: ](https://app.codecov.io/gh/apache/superset/pull/44003?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) |
| [superset/commands/database/update.py](https://app.codecov.io/gh/apache/superset/pull/44003?src=pr&el=tree&filepath=superset%2Fcommands%2Fdatabase%2Fupdate.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-c3VwZXJzZXQvY29tbWFuZHMvZGF0YWJhc2UvdXBkYXRlLnB5) | 17.39% | [19 Missing :warning: ](https://app.codecov.io/gh/apache/superset/pull/44003?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) |
| [superset/commands/database/test\_connection.py](https://app.codecov.io/gh/apache/superset/pull/44003?src=pr&el=tree&filepath=superset%2Fcommands%2Fdatabase%2Ftest_connection.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-c3VwZXJzZXQvY29tbWFuZHMvZGF0YWJhc2UvdGVzdF9jb25uZWN0aW9uLnB5) | 18.18% | [9 Missing :warning: ](https://app.codecov.io/gh/apache/superset/pull/44003?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) |
| [superset/commands/database/importers/v1/utils.py](https://app.codecov.io/gh/apache/superset/pull/44003?src=pr&el=tree&filepath=superset%2Fcommands%2Fdatabase%2Fimporters%2Fv1%2Futils.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-c3VwZXJzZXQvY29tbWFuZHMvZGF0YWJhc2UvaW1wb3J0ZXJzL3YxL3V0aWxzLnB5) | 12.50% | [7 Missing :warning: ](https://app.codecov.io/gh/apache/superset/pull/44003?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) |
| [superset/commands/database/validate.py](https://app.codecov.io/gh/apache/superset/pull/44003?src=pr&el=tree&filepath=superset%2Fcommands%2Fdatabase%2Fvalidate.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-c3VwZXJzZXQvY29tbWFuZHMvZGF0YWJhc2UvdmFsaWRhdGUucHk=) | 12.50% | [7 Missing :warning: ](https://app.codecov.io/gh/apache/superset/pull/44003?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) |
| [superset/daos/database.py](https://app.codecov.io/gh/apache/superset/pull/44003?src=pr&el=tree&filepath=superset%2Fdaos%2Fdatabase.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-c3VwZXJzZXQvZGFvcy9kYXRhYmFzZS5weQ==) | 25.00% | [3 Missing :warning: ](https://app.codecov.io/gh/apache/superset/pull/44003?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) |
| [superset/commands/database/exceptions.py](https://app.codecov.io/gh/apache/superset/pull/44003?src=pr&el=tree&filepath=superset%2Fcommands%2Fdatabase%2Fexceptions.py&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#diff-c3VwZXJzZXQvY29tbWFuZHMvZGF0YWJhc2UvZXhjZXB0aW9ucy5weQ==) | 80.00% | [1 Missing :warning: ](https://app.codecov.io/gh/apache/superset/pull/44003?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) |
> :exclamation: There is a different number of reports uploaded between BASE (c4e145b) and HEAD (87a5280). Click for more details.
>
> <details><summary>HEAD has 93 uploads less than BASE</summary>
>
>| Flag | BASE (c4e145b) | HEAD (87a5280) |
>|------|------|------|
>|python|73|2|
>|presto|12|1|
>|hive|12|1|
></details>
<details><summary>Additional details and impacted files</summary>
```diff
@@ Coverage Diff @@
## master #44003 +/- ##
===========================================
- Coverage 79.81% 57.53% -22.28%
===========================================
Files 2914 2914
Lines 170473 170543 +70
Branches 39518 39529 +11
===========================================
- Hits 136066 98127 -37939
- Misses 31885 71494 +39609
+ Partials 2522 922 -1600
```
| [Flag](https://app.codecov.io/gh/apache/superset/pull/44003/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | Coverage ฮ | |
|---|---|---|
| [hive](https://app.codecov.io/gh/apache/superset/pull/44003/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | `37.62% <25.27%> (-0.01%)` | :arrow_down: |
| [mysql](https://app.codecov.io/gh/apache/superset/pull/44003/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | `?` | |
| [postgres](https://app.codecov.io/gh/apache/superset/pull/44003/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | `?` | |
| [presto](https://app.codecov.io/gh/apache/superset/pull/44003/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | `39.50% <25.27%> (-0.01%)` | :arrow_down: |
| [python](https://app.codecov.io/gh/apache/superset/pull/44003/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | `39.55% <25.27%> (-44.64%)` | :arrow_down: |
| [sqlite](https://app.codecov.io/gh/apache/superset/pull/44003/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | `?` | |
| [unit](https://app.codecov.io/gh/apache/superset/pull/44003/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | `?` | |
Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#carryforward-flags-in-the-pull-request-comment) to find out more.
</details>
[:umbrella: View full report in Codecov by Harness](https://app.codecov.io/gh/apache/superset/pull/44003?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache).
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache).
<details><summary> :rocket: New features to boost your workflow: </summary>
- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
- :package: [JS Bundle Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
</details>
--
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: notifications-unsubscribe@superset.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org
Re: [PR] fix(database): don't reattach stored connection details when the effective destination changes [superset]
Posted by "codeant-ai-for-open-source[bot] (via GitHub)" <gi...@apache.org>.
codeant-ai-for-open-source[bot] commented on code in PR #44003:
URL: https://github.com/apache/superset/pull/44003#discussion_r3959514012
##########
superset/commands/database/update.py:
##########
@@ -180,3 +188,50 @@ def validate(self) -> None:
database_name,
):
raise DatabaseInvalidError(exceptions=[DatabaseExistsValidationError()])
+
+ if self._model:
+ self._check_no_unsafe_secret_rebind()
+
+ def _check_no_unsafe_secret_rebind(self) -> None:
+ """
+ Refuse an update that changes the connection's effective destination
+ (URI host/port, `extra.engine_params`, or the SSH tunnel endpoint)
+ while leaving the corresponding stored secret masked.
+
+ Without this, an editor could silently redirect the real stored
+ password/encrypted_extra/SSH tunnel credential to a different
+ destination -- and since an update persists, every subsequent use of
+ the database (by any user) would send the real secret there, not
+ just the editor's own request.
+ """
+ model = self._model
+ assert model is not None
+
+ connection_identity_changed = False
+ submitted_password: str | None = None
+
+ if "sqlalchemy_uri" in self._properties:
+ submitted_uri = self._properties["sqlalchemy_uri"] or ""
+ connection_identity_changed = uri_identity_changed(
+ model.sqlalchemy_uri, submitted_uri
+ )
+ try:
+ submitted_password = make_url_safe(submitted_uri).password
+ except DatabaseInvalidError:
+ submitted_password = None
+
+ if "extra" in self._properties and engine_params_changed(
+ model.extra, self._properties["extra"]
+ ):
+ connection_identity_changed = True
+
+ if connection_identity_changed and submitted_password in (
+ None,
+ PASSWORD_MASK,
+ ):
+ raise DatabaseInvalidError(exceptions=[DatabaseUpdateUnsafeRebindError()])
Review Comment:
**Suggestion:** A destination change is accepted only when the URI contains a real password, so fresh `masked_encrypted_extra` credentials are rejected for engines storing authentication outside the URI. [api mismatch]
**Assessment:** ๐ `Major` ยท ๐ `Occurrence: Sometimes`
[](https://docs.codeant.ai/cli/resolve-pr-comments-skill) [](https://app.codeant.ai/fix-in-ide?tool=cursor&prompt_id=54e164d592c342a4aed9063f5894981f&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset) [](https://app.codeant.ai/fix-in-ide?tool=vscode-claude&prompt_id=54e164d592c342a4aed9063f5894981f&service=github&base_url=https%3A%2F%2Fgithub.com&org=apache&repo=apache%2Fsuperset)
<details>
<summary><b>Prompt for AI Agent ๐ค </b></summary>
```mdx
This is a comment left during a code review.
**Path:** superset/commands/database/update.py
**Line:** 228:232
**Comment:**
*Api Mismatch: A destination change is accepted only when the URI contains a real password, so fresh `masked_encrypted_extra` credentials are rejected for engines storing authentication outside the URI.
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
```
</details>
<a href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F44003&comment_hash=6621f16978bffd3b993b04a4b1c34b95a700e37fdc727a1d700723b73a25f2b3&reaction=like'>๐</a> | <a href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F44003&comment_hash=6621f16978bffd3b993b04a4b1c34b95a700e37fdc727a1d700723b73a25f2b3&reaction=dislike'>๐</a>
--
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: notifications-unsubscribe@superset.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org
Re: [PR] fix(database): don't reattach stored connection details when the effective destination changes [superset]
Posted by "rusackas (via GitHub)" <gi...@apache.org>.
rusackas commented on PR #44003:
URL: https://github.com/apache/superset/pull/44003#issuecomment-5588488616
Went through Bito's additional suggestions and sha174n's inline review, pushed a follow-up commit (72ccf98) addressing what checked out:
**Taken:**
- The `encrypted_extra` reuse gap in `update.py` (Bito's CWE-200 finding, sha174n's more detailed version with a suggestion block) โ real gap, took sha174n's fix with two refinements (check `model.password is not None` instead of re-deriving via the masked URI, and exclude an empty `"{}"` `encrypted_extra` from being treated as a stored secret).
- `daos/database.py`'s duplicate base-filter logic โ `DatabaseDAO._apply_base_filter` exists upstream now (landed after this branch was first opened), swapped the manual reimplementation for it.
- The SSH tunnel gating bug flagged on `validate.py` โ real, and it turned out to also exist in `test_connection.py` (same pattern, just not flagged there). Both now gate the tunnel's own password unmask on whether the tunnel endpoint itself changed, not the combined identity flag, so an unrelated `engine_params` edit no longer spuriously breaks a legitimate tunneled connection test.
- The `field_name` misattribution on `DatabaseUpdateUnsafeRebindError` โ parameterized it so the SSH-tunnel-only rebind case attributes its 422 correctly.
**Not taken:** the three "narrow `engine_params` comparison to host/port only" suggestions (`update.py`, `test_connection.py`, `importers/v1/utils.py`). The false-positive concern is real, but the fix as proposed is a regression risk as-is โ Postgres has `hostaddr` as a second way to redirect the destination independent of `host`, and I haven't audited whether an equivalent exists across the other engine specs this code touches. Narrowing the comparison without that audit could reopen the exact bug this PR closes for some driver. Left the conservative whole-dict comparison in place; the usability cost seems like a reasonable follow-up issue for someone to do that audit properly rather than something to rush into a security-relevant PR.
Regression tests added for everything taken above, each verified to fail without its fix and pass with it.
--
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: notifications-unsubscribe@superset.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org
Re: [PR] fix(database): don't reattach stored connection details when the effective destination changes [superset]
Posted by "rusackas (via GitHub)" <gi...@apache.org>.
rusackas commented on code in PR #44003:
URL: https://github.com/apache/superset/pull/44003#discussion_r3960099224
##########
superset/commands/database/update.py:
##########
@@ -180,3 +188,50 @@ def validate(self) -> None:
database_name,
):
raise DatabaseInvalidError(exceptions=[DatabaseExistsValidationError()])
+
+ if self._model:
+ self._check_no_unsafe_secret_rebind()
+
+ def _check_no_unsafe_secret_rebind(self) -> None:
+ """
+ Refuse an update that changes the connection's effective destination
+ (URI host/port, `extra.engine_params`, or the SSH tunnel endpoint)
+ while leaving the corresponding stored secret masked.
+
+ Without this, an editor could silently redirect the real stored
+ password/encrypted_extra/SSH tunnel credential to a different
+ destination -- and since an update persists, every subsequent use of
+ the database (by any user) would send the real secret there, not
+ just the editor's own request.
+ """
+ model = self._model
+ assert model is not None
+
+ connection_identity_changed = False
+ submitted_password: str | None = None
+
+ if "sqlalchemy_uri" in self._properties:
+ submitted_uri = self._properties["sqlalchemy_uri"] or ""
+ connection_identity_changed = uri_identity_changed(
+ model.sqlalchemy_uri, submitted_uri
+ )
+ try:
+ submitted_password = make_url_safe(submitted_uri).password
+ except DatabaseInvalidError:
+ submitted_password = None
+
+ if "extra" in self._properties and engine_params_changed(
+ model.extra, self._properties["extra"]
+ ):
+ connection_identity_changed = True
+
+ if connection_identity_changed and submitted_password in (
+ None,
+ PASSWORD_MASK,
+ ):
+ raise DatabaseInvalidError(exceptions=[DatabaseUpdateUnsafeRebindError()])
Review Comment:
Applied it (and refined the URI-password / encrypted_extra checks a bit further, plus fixed the same field_name/ssh_tunnel-gating issues Bito's pass caught nearby) in 72ccf98. Added regression tests for the false-positive and the actual reuse gap, both verified to fail without the fix. Thanks for catching this.
##########
superset/commands/database/update.py:
##########
@@ -180,3 +188,50 @@ def validate(self) -> None:
database_name,
):
raise DatabaseInvalidError(exceptions=[DatabaseExistsValidationError()])
+
+ if self._model:
+ self._check_no_unsafe_secret_rebind()
+
+ def _check_no_unsafe_secret_rebind(self) -> None:
+ """
+ Refuse an update that changes the connection's effective destination
+ (URI host/port, `extra.engine_params`, or the SSH tunnel endpoint)
+ while leaving the corresponding stored secret masked.
+
+ Without this, an editor could silently redirect the real stored
+ password/encrypted_extra/SSH tunnel credential to a different
+ destination -- and since an update persists, every subsequent use of
+ the database (by any user) would send the real secret there, not
+ just the editor's own request.
+ """
+ model = self._model
+ assert model is not None
+
+ connection_identity_changed = False
+ submitted_password: str | None = None
+
+ if "sqlalchemy_uri" in self._properties:
+ submitted_uri = self._properties["sqlalchemy_uri"] or ""
+ connection_identity_changed = uri_identity_changed(
+ model.sqlalchemy_uri, submitted_uri
+ )
+ try:
+ submitted_password = make_url_safe(submitted_uri).password
+ except DatabaseInvalidError:
+ submitted_password = None
+
+ if "extra" in self._properties and engine_params_changed(
+ model.extra, self._properties["extra"]
+ ):
+ connection_identity_changed = True
+
+ if connection_identity_changed and submitted_password in (
+ None,
+ PASSWORD_MASK,
+ ):
+ raise DatabaseInvalidError(exceptions=[DatabaseUpdateUnsafeRebindError()])
Review Comment:
Correct catch, this and sha174n's more detailed suggestion on the same lines are the same underlying gap. Fixed in 72ccf98 (see reply on that thread for detail).
--
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: notifications-unsubscribe@superset.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org
Re: [PR] fix(database): don't reattach stored connection details when the effective destination changes [superset]
Posted by "rusackas (via GitHub)" <gi...@apache.org>.
rusackas merged PR #44003:
URL: https://github.com/apache/superset/pull/44003
--
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: notifications-unsubscribe@superset.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org
Re: [PR] fix(database): don't reattach stored connection details when the effective destination changes [superset]
Posted by "bito-code-review[bot] (via GitHub)" <gi...@apache.org>.
bito-code-review[bot] commented on PR #44003:
URL: https://github.com/apache/superset/pull/44003#issuecomment-5594374287
**Bito Automatic Review Skipped โ PR Already Merged**<br/><br/>Bito scheduled an automatic review for this pull request, but the review was skipped because this PR was merged before the review could be run.<br/>No action is needed if you didn't intend to review it. To get a review, you can type `/review` in a comment and save it
--
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: notifications-unsubscribe@superset.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org
Re: [PR] fix(database): don't reattach stored connection details when the effective destination changes [superset]
Posted by "sha174n (via GitHub)" <gi...@apache.org>.
sha174n commented on code in PR #44003:
URL: https://github.com/apache/superset/pull/44003#discussion_r3959662653
##########
superset/commands/database/update.py:
##########
@@ -180,3 +188,50 @@ def validate(self) -> None:
database_name,
):
raise DatabaseInvalidError(exceptions=[DatabaseExistsValidationError()])
+
+ if self._model:
+ self._check_no_unsafe_secret_rebind()
+
+ def _check_no_unsafe_secret_rebind(self) -> None:
+ """
+ Refuse an update that changes the connection's effective destination
+ (URI host/port, `extra.engine_params`, or the SSH tunnel endpoint)
+ while leaving the corresponding stored secret masked.
+
+ Without this, an editor could silently redirect the real stored
+ password/encrypted_extra/SSH tunnel credential to a different
+ destination -- and since an update persists, every subsequent use of
+ the database (by any user) would send the real secret there, not
+ just the editor's own request.
+ """
+ model = self._model
+ assert model is not None
+
+ connection_identity_changed = False
+ submitted_password: str | None = None
+
+ if "sqlalchemy_uri" in self._properties:
+ submitted_uri = self._properties["sqlalchemy_uri"] or ""
+ connection_identity_changed = uri_identity_changed(
+ model.sqlalchemy_uri, submitted_uri
+ )
+ try:
+ submitted_password = make_url_safe(submitted_uri).password
+ except DatabaseInvalidError:
+ submitted_password = None
+
+ if "extra" in self._properties and engine_params_changed(
+ model.extra, self._properties["extra"]
+ ):
+ connection_identity_changed = True
+
+ if connection_identity_changed and submitted_password in (
+ None,
+ PASSWORD_MASK,
+ ):
+ raise DatabaseInvalidError(exceptions=[DatabaseUpdateUnsafeRebindError()])
Review Comment:
The rebind check here covers the URI password and (separately) the SSH tunnel, but not `encrypted_extra`. Since a masked `masked_encrypted_extra` is reattached to the submitted destination via `unmask_encrypted_extra` in `run()`, gating only on the URI password (a) rejects legitimate destination changes for engines that keep auth in `encrypted_extra` and carry no URI password (e.g. BigQuery, GSheets), and (b) lets a reused `encrypted_extra` carry over when a fresh URI password is supplied. Suggest gating `encrypted_extra` on its own freshness too, the way the SSH-tunnel path already does:
```suggestion
if connection_identity_changed:
try:
stored_uri_password = make_url_safe(model.sqlalchemy_uri).password
except DatabaseInvalidError:
stored_uri_password = None
uri_password_reused = stored_uri_password is not None and (
submitted_password in (None, PASSWORD_MASK)
)
# encrypted_extra is a blob with per-field masks, so "reused" means
# unmasking the submission against the stored value changes nothing.
encrypted_extra_reused = bool(model.encrypted_extra) and (
"masked_encrypted_extra" not in self._properties
or model.db_engine_spec.unmask_encrypted_extra(
model.encrypted_extra,
self._properties["masked_encrypted_extra"],
)
== model.encrypted_extra
)
if uri_password_reused or encrypted_extra_reused:
raise DatabaseInvalidError(
exceptions=[DatabaseUpdateUnsafeRebindError()]
)
```
One caveat: `bool(model.encrypted_extra)` slightly over-triggers when `encrypted_extra` is present but holds no secret (e.g. `"{}"`); a "has stored secret" check would be tighter. The same pattern applies anywhere else a stored `encrypted_extra` is reattached on a changed destination.
--
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: notifications-unsubscribe@superset.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org
Re: [PR] fix(database): don't reattach stored connection details when the effective destination changes [superset]
Posted by "netlify[bot] (via GitHub)" <gi...@apache.org>.
netlify[bot] commented on PR #44003:
URL: https://github.com/apache/superset/pull/44003#issuecomment-5588962239
### <span aria-hidden="true">โ
</span> Deploy Preview for *superset-docs-preview* ready!
| Name | Link |
|:-:|------------------------|
|<span aria-hidden="true">๐จ</span> Latest commit | 527bef35f61418ec83f6c5bac9c141e05d7d9ee4 |
|<span aria-hidden="true">๐</span> Latest deploy log | https://app.netlify.com/projects/superset-docs-preview/deploys/6aa040d1bf90a700082bb6ac |
|<span aria-hidden="true">๐</span> Deploy Preview | [https://deploy-preview-44003--superset-docs-preview.netlify.app](https://deploy-preview-44003--superset-docs-preview.netlify.app) |
|<span aria-hidden="true">๐ฑ</span> Preview on mobile | <details><summary> Toggle QR Code... </summary><br /><br /><br /><br />_Use your smartphone camera to open QR code link._</details> |
|<span aria-hidden="true">๐ค</span> Make changes | [Run an agent on this branch](https://app.netlify.com/projects/superset-docs-preview/agent-runs#DctLDoIwEADQu8zaxtGYKtzAY8yP0CjTBmcBIdzd7t7mHdDWurSAEeACvJLL3D2V7aoUxPSzJNXdJEr1VNQ8SuxJZpNPH2rtW_e39pOJ8IF642lAeiLi686cSeD8Aw) |
---
<!-- [superset-docs-preview Preview](https://deploy-preview-44003--superset-docs-preview.netlify.app) -->
_To edit notification comments on pull requests, go to your [Netlify project configuration](https://app.netlify.com/projects/superset-docs-preview/configuration/notifications#deploy-notifications)._
--
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: notifications-unsubscribe@superset.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@superset.apache.org
For additional commands, e-mail: notifications-help@superset.apache.org