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]

Reply via email to