Skip to content

fix(encryption): resolve SECRET_KEY lazily to fix silent re-encrypt-secrets failures#37982

Open
Ujjwaljain16 wants to merge 4 commits intoapache:masterfrom
Ujjwaljain16:fix/encryption-lazy-key-resolution
Open

fix(encryption): resolve SECRET_KEY lazily to fix silent re-encrypt-secrets failures#37982
Ujjwaljain16 wants to merge 4 commits intoapache:masterfrom
Ujjwaljain16:fix/encryption-lazy-key-resolution

Conversation

@Ujjwaljain16
Copy link

SUMMARY

Fixes an issue where superset re-encrypt-secrets could silently fail to rotate encrypted database secrets.

Previously, EncryptedType was initialized with a static string value of SECRET_KEY at model definition time:

EncryptedType(*args, app_config["SECRET_KEY"], **kwargs)

If configuration overrides (e.g., SUPERSET_SECRET_KEY, Helm updates, or runtime changes) occurred after model import, the encryption engine could remain bound to a stale key.

During key rotation:

  • Decryption with PREVIOUS_SECRET_KEY succeeded.
  • Re-encryption reused the model’s existing EncryptedType.
  • If that instance still held the old key, data was written back unchanged.
  • The command exited successfully but performed no effective rotation.

After restart with the new SECRET_KEY, Superset would fail with:

ValueError: Invalid decryption key

Fix

Pass a callable instead of a static string to EncryptedType:

- return EncryptedType(*args, app_config["SECRET_KEY"], **kwargs)
+ return EncryptedType(*args, lambda: app_config["SECRET_KEY"], **kwargs)

sqlalchemy-utils supports callable keys and resolves them on every encrypt/decrypt operation. This ensures the current SECRET_KEY is always used at runtime.

No schema changes or data format changes are introduced.

Tests

  • Updated existing test to assert callable key behavior.
  • Added test_lazy_key_resolution to verify key changes are reflected after field creation.
  • Added test_secret_key_rotation to simulate end-to-end key rotation (KEY_A → KEY_B) and verify correct decryption behavior.

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

Not applicable (backend encryption fix).


TESTING INSTRUCTIONS

Manual verification:

  1. Start Superset with SECRET_KEY = A.

  2. Create a database connection with a password.

  3. Rotate keys:

    PREVIOUS_SECRET_KEY = A
    SECRET_KEY = B
    superset re-encrypt-secrets
    
  4. Restart Superset.

  5. Confirm database connections decrypt successfully under B.

  6. Confirm reverting to A causes decryption failure.

Unit tests cover lazy key resolution and full rotation behavior.


ADDITIONAL INFORMATION


@bito-code-review
Copy link
Contributor

bito-code-review bot commented Feb 15, 2026

Code Review Agent Run #e4fcc6

Actionable Suggestions - 0
Review Details
  • Files reviewed - 4 · Commit Range: 5b817f5..1a36a59
    • superset-frontend/packages/superset-ui-core/src/components/ModalTrigger/ModalTrigger.test.tsx
    • superset-frontend/packages/superset-ui-core/src/components/ModalTrigger/index.tsx
    • superset/utils/encrypt.py
    • tests/integration_tests/utils/encrypt_tests.py
  • Files skipped - 0
  • 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

@dosubot dosubot bot added the change:backend Requires changing the backend label Feb 15, 2026
@Ujjwaljain16 Ujjwaljain16 force-pushed the fix/encryption-lazy-key-resolution branch from 1a36a59 to ebd2f42 Compare February 15, 2026 05:00
@pull-request-size pull-request-size bot added size/M and removed size/L labels Feb 15, 2026
@github-actions github-actions bot removed the packages label Feb 15, 2026
@hainenber
Copy link
Contributor

@Ujjwaljain16 thanks for making contribution here! However, this PR contains commits from other PRs you've pushed to. Can you clean that up?

# If decryption doesn't raise, value should be garbage
assert bad_decrypt != test_value
except (ValueError, Exception):
pass # Expected: old key cannot decrypt new ciphertext
Copy link
Contributor

Choose a reason for hiding this comment

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

there should be an assertion here for the thrown error to ensure that indeed it's the decryption issue

@bito-code-review
Copy link
Contributor

Adding an assertion to ensure decryption fails with the wrong key would strengthen the test by confirming the error is due to key mismatch, not just producing incorrect output. This makes the test more robust.

tests/integration_tests/utils/encrypt_tests.py

# Step 6: Verify KEY_A can no longer decrypt the new ciphertext
        self.app.config["SECRET_KEY"] = key_a
        with pytest.raises(ValueError):
            field.process_result_value(encrypted_b, dialect)

@Ujjwaljain16
Copy link
Author

@hainenber yes that's my mistake and i cleaned that up

@codecov
Copy link

codecov bot commented Feb 15, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 66.43%. Comparing base (76d897e) to head (38fa4d3).
⚠️ Report is 3750 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #37982      +/-   ##
==========================================
+ Coverage   60.48%   66.43%   +5.94%     
==========================================
  Files        1931      668    -1263     
  Lines       76236    51322   -24914     
  Branches     8568     5776    -2792     
==========================================
- Hits        46114    34096   -12018     
+ Misses      28017    15840   -12177     
+ Partials     2105     1386     -719     
Flag Coverage Δ
hive 41.47% <100.00%> (-7.68%) ⬇️
javascript ?
mysql 64.53% <100.00%> (?)
postgres 64.61% <100.00%> (?)
presto 41.49% <100.00%> (-12.32%) ⬇️
python 66.40% <100.00%> (+2.90%) ⬆️
sqlite 64.20% <100.00%> (?)
unit 100.00% <ø> (+42.36%) ⬆️

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

☔ View full report in Codecov by Sentry.
📢 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.

@hainenber
Copy link
Contributor

This has been working out greatly! Having said that, I think @dpgaspar's would have better authority for the full review.

@hainenber hainenber requested a review from dpgaspar February 15, 2026 06:02
@hainenber hainenber added the authentication Related to authentication label Feb 15, 2026
@bito-code-review
Copy link
Contributor

bito-code-review bot commented Feb 15, 2026

Code Review Agent Run #11854e

Actionable Suggestions - 0
Review Details
  • Files reviewed - 2 · Commit Range: ebd2f42..328f4ae
    • superset/utils/encrypt.py
    • tests/integration_tests/utils/encrypt_tests.py
  • Files skipped - 0
  • 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

@bito-code-review
Copy link
Contributor

bito-code-review bot commented Feb 15, 2026

Code Review Agent Run #f386e4

Actionable Suggestions - 0
Review Details
  • Files reviewed - 2 · Commit Range: 328f4ae..38fa4d3
    • superset/utils/encrypt.py
    • tests/integration_tests/utils/encrypt_tests.py
  • Files skipped - 0
  • 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

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

Labels

authentication Related to authentication change:backend Requires changing the backend size/M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

superset re-encrypt-secrets effectively not working

2 participants