Repository navigation
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #45353 +/- ##
=======================================
Coverage 84.93% 84.93%
=======================================
Files 3077 3077
Lines 208202 208243 +41
Branches 49105 49118 +13
=======================================
+ Hits 176831 176868 +37
- Misses 28002 28004 +2
- Partials 3369 3371 +2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
… log The event logger stores each request's form, args and JSON body, so the Action Log kept every secret typed into the database dialog, a connection test or an import in clear: database passwords, SSH tunnel credentials, OAuth2 client secrets, embedded fallback credentials, and the import password and encrypted_extra_secrets maps. collect_request_payload now masks the value of any sensitive key at any depth, and keeps sqlalchemy_uri readable with only its password masked. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A SQLAlchemy URI can carry its credential in the query string (motherduck_token, azure_ad_client_secret), under names particular to each engine, and such a URI was logged unchanged. Mask every query value, in the URI and in the form's parameters.query that builds it, rather than keep a list of names that would leak the next one. Also mask whole a URI whose parsed host holds an "@", which is what remains of an unencoded "@" in the password, and any non-string sqlalchemy_uri. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
97c7714 to
8363b4d
Compare
aminghadersohi
left a comment
There was a problem hiding this comment.
Some supported connection credentials still reach the Action Log.
| "private_key", | ||
| "private_key_password", | ||
| "privatekey_body", | ||
| "privatekey_pass", |
There was a problem hiding this comment.
query_input duplicates the Additional Parameters text beside parameters.query, but only the latter is masked. Entering sslpassword=... still records the credential on validation/save; mask query_input too.
| "privatekey_pass", | |
| "privatekey_pass", | |
| "query_input", |
| if url.password is None and not url.query: | ||
| return uri |
There was a problem hiding this comment.
Arc API keys and Dremio ODBC tokens occupy the URI username, so they still reach Action Log records verbatim, with or without query parameters. Mask these credential-bearing usernames before returning the URI.
| if url.password is None and not url.query: | |
| return uri | |
| if url.username and ( | |
| url.drivername.split("+", 1)[0] == "arc" | |
| or url.drivername == "dremio+pyodbc" | |
| ): | |
| return PASSWORD_MASK | |
| if url.password is None and not url.query: | |
| return uri |
| if url.host and "@" in url.host: | ||
| return PASSWORD_MASK |
There was a problem hiding this comment.
Nit: An unencoded '@' followed by '/' or '?' can leave part of a password outside the parsed host, bypassing this check. For example, postgresql://user:p@ss/word@host/db still logs ss/word; mask the whole ambiguous URI.
| if url.host and "@" in url.host: | |
| return PASSWORD_MASK | |
| if (url.host and "@" in url.host) or ( | |
| url.password is not None and uri.count("@") > 1 | |
| ): | |
| return PASSWORD_MASK |
SUMMARY
The event logger stores each request's form, args and JSON body, so the Action Log kept every secret typed into the database dialog, a connection test or an import in clear (database and SSH tunnel passwords, OAuth2 client secrets, embedded fallback credentials, import password /
encrypted_extra_secretsmaps).collect_request_payloadnow masks the value of any sensitive key at any depth and keepssqlalchemy_urireadable with its password and query values masked.TESTING INSTRUCTIONS
pytest tests/unit_tests/utils/log_tests.py tests/unit_tests/databases/api_test.py -k "redact or never_carries or never_records". The two end-to-end tests fail without the change.ADDITIONAL INFORMATION
🤖 Generated with Claude Code