Escaping the % character as %25 in the password within the connection string does not work
Bug description
When establishing a database connection, simply escaping the % character as %25 in the password within the connection string does not work.
The root cause was identified in superset/models/core.py. The error occurs in the sqlalchemy_uri_decrypted function at the statement return str(conn). str(conn) make %25 to % and then make_url() make % disappear.
A workaround is replacing %25 by %2525.
Screenshots/recordings
No response
Superset version
master / 6.0rc3
Python version
3.11
Node version
16
Browser
Chrome
Additional context
No response
Checklist
- [x] I have searched Superset docs and Slack and didn't find a solution to my problem.
- [x] I have searched the GitHub issue tracker and didn't find a similar bug report.
- [ ] I have checked Superset's logs for errors and if I found a relevant Python stacktrace, I included it here as text in the "additional context" section.
Hi @i-love-thinking! I'm Dosu and I’m helping the superset team.
This happens because Superset (and SQLAlchemy) decode percent-encoded values in connection strings during parsing and stringification. When you use %25 for %, the flow in Superset's code (specifically in sqlalchemy_uri_decrypted) converts %25 back to % when calling str(conn), and then reparsing the string can cause the % to disappear or trigger errors unless it's double-escaped. That's why %2525 (which decodes to %25, then to %) works as a workaround reference.
This issue has been addressed in recent Superset versions (see PR #30532), but the safest approach is to double-escape % as %% or %2525 in your password if you encounter this problem. For all special characters, always URL-encode your password (e.g., with urllib.parse.quote_plus), but for %, double-escaping is required due to the round-trip parsing and stringification reference.
For more details, see the related issues and SQLAlchemy docs on escaping special characters in passwords.
To reply, just mention @dosu.
How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other
Can you validate the bot's comments here? Sounds correct...
I can confirm this behavior — the percent-encoding round-trip does break passwords containing % because str(conn) collapses %25 back to %, and reparsing removes it. I can work on a small fix in sqlalchemy_uri_decrypted and add a round-trip unit test if no one else is already working on it.
Please let me know if I may proceed with a PR.