Eason09053360 opened a new pull request, #73157:
URL: https://github.com/apache/airflow/pull/73157
## Why
`airflow connections list --show-values --hide-sensitive` exists so its
output can be pasted into a bug report or kept in a log, and the flag's help
promises to mask "passwords, URI credentials, extra". The `get_uri` column
broke that promise in two ways, while the neighbouring `password` and
`extra_dejson` columns masked correctly — so the leak is easy to miss when
eyeballing the output.
1. **`extra` was printed verbatim.** `Connection.get_uri()` serialises
`extra` into the query string, and the masking helper only ever looked at
credentials in `netloc`:
```
password | extra_dejson | get_uri
*** | *** |
http://***:***@example.com/?api_key=SUPERSECRETKEY
```
2. **The password leaked too when `host` carries its own scheme.**
`get_uri()` then emits a doubled scheme, which `urlsplit` parses as netloc
`https:` with the credentials left in `path`, so the `"@" in netloc` guard
never fired:
```
http://https://alice:[email protected]/?api_key=SUPERSECRETKEY
(unmasked)
```
related: #59838
## What
`_mask_uri_credentials` in
`airflow-core/src/airflow/cli/commands/connection_command.py` now masks the
query string as a whole — matching how the `extra_dejson` column in the same
mapper treats `extra` — and takes the authority from the last `://` instead of
trusting `parsed.netloc`.
Both spans are substituted in the original string rather than reassembled
with `urlunsplit`, which mangles URIs with an empty authority (`filesystem://`
→ `filesystem:`, `http:///?…` → `http:/?…`) — reachable here because a
connection can have `extra` without a host.
Output for the four connection shapes:
```
http://alice:[email protected]/?api_key=SECRET ->
http://***:***@example.com/?***
http://https://alice:[email protected]/?api_key=SECRET ->
http://https://***:***@api.example.com/?***
http://example.com/?api_key=SECRET ->
http://example.com/?***
http:///?api_key=SECRET -> http:///?***
```
Connections with nothing to mask (`redis://localhost:6379/0`,
`sqlite:///tmp/test.db`) are returned byte-for-byte unchanged.
Tests in `airflow-core/tests/unit/cli/commands/test_connection_command.py`
cover both leaks, including two cases that build a real `Connection` and assert
the secret is absent from `_mask_uri_credentials(conn.get_uri())`. All eight
new cases fail without the change.
---
##### Was generative AI tooling used to co-author this PR?
- [X] Yes — Claude Code (Opus 5)
Generated-by: Claude Code (Opus 5) following [the
guidelines](https://github.com/apache/airflow/blob/main/contributing-docs/05_pull_requests.rst#gen-ai-assisted-contributions)
--
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: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]