This is an automated email from the ASF dual-hosted git repository.

potiuk pushed a commit to branch v3-1-test
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/v3-1-test by this push:
     new 2504bd660de [v3-1-test] Prevent client secrets and proxy credentials 
from being logged in Microsoft Graph hook logs (#59688) (#59792)
2504bd660de is described below

commit 2504bd660dec4e2958016984dfe4900eb900b280
Author: Ankit Chaurasia <[email protected]>
AuthorDate: Fri Dec 26 05:01:41 2025 +0545

    [v3-1-test] Prevent client secrets and proxy credentials from being logged 
in Microsoft Graph hook logs (#59688) (#59792)
    
    Prevent client secrets and proxy credentials from being logged in Microsoft 
Graph hook logs (#59688)
    (cherry picked from commit a9dea6d0b81d67843c2507bd85af772fde9dd738)
---
 airflow-core/newsfragments/59688.improvement.rst    |  1 +
 .../providers/microsoft/azure/hooks/msgraph.py      | 10 ++++++----
 .../unit/microsoft/azure/hooks/test_msgraph.py      | 21 +++++++++++++++++++++
 .../airflow_shared/secrets_masker/secrets_masker.py |  2 ++
 task-sdk/src/airflow/sdk/log.py                     |  4 +---
 5 files changed, 31 insertions(+), 7 deletions(-)

diff --git a/airflow-core/newsfragments/59688.improvement.rst 
b/airflow-core/newsfragments/59688.improvement.rst
new file mode 100644
index 00000000000..d3c592cfcc3
--- /dev/null
+++ b/airflow-core/newsfragments/59688.improvement.rst
@@ -0,0 +1 @@
+Add ``proxy`` and ``proxies`` to ``DEFAULT_SENSITIVE_FIELDS`` in 
secrets_masker to treat proxy configurations as sensitive by default
diff --git 
a/providers/microsoft/azure/src/airflow/providers/microsoft/azure/hooks/msgraph.py
 
b/providers/microsoft/azure/src/airflow/providers/microsoft/azure/hooks/msgraph.py
index 958a3b8f437..775f0097602 100644
--- 
a/providers/microsoft/azure/src/airflow/providers/microsoft/azure/hooks/msgraph.py
+++ 
b/providers/microsoft/azure/src/airflow/providers/microsoft/azure/hooks/msgraph.py
@@ -63,6 +63,8 @@ if TYPE_CHECKING:
 
     from airflow.models import Connection
 
+from airflow_shared.secrets_masker import redact
+
 
 class DefaultResponseHandler(ResponseHandler):
     """DefaultResponseHandler returns JSON payload or content in bytes or 
response headers."""
@@ -272,7 +274,7 @@ class KiotaRequestAdapterHook(BaseHook):
         self.log.info("Host: %s", host)
         self.log.info("Base URL: %s", base_url)
         self.log.info("Client id: %s", client_id)
-        self.log.info("Client secret: %s", client_secret)
+        self.log.info("Client secret: %s", redact(client_secret, 
name="client_secret"))
         self.log.info("API version: %s", api_version)
         self.log.info("Scope: %s", scopes)
         self.log.info("Verify: %s", verify)
@@ -280,8 +282,8 @@ class KiotaRequestAdapterHook(BaseHook):
         self.log.info("Trust env: %s", trust_env)
         self.log.info("Authority: %s", authority)
         self.log.info("Allowed hosts: %s", allowed_hosts)
-        self.log.info("Proxies: %s", proxies)
-        self.log.info("HTTPX Proxies: %s", httpx_proxies)
+        self.log.info("Proxies: %s", redact(proxies, name="proxies"))
+        self.log.info("HTTPX Proxies: %s", redact(httpx_proxies, 
name="proxies"))
         credentials = self.get_credentials(
             login=connection.login,
             password=connection.password,
@@ -391,7 +393,7 @@ class KiotaRequestAdapterHook(BaseHook):
         self.log.info("Certificate data: %s", certificate_data is not None)
         self.log.info("Authority: %s", authority)
         self.log.info("Disable instance discovery: %s", 
disable_instance_discovery)
-        self.log.info("MSAL Proxies: %s", msal_proxies)
+        self.log.info("MSAL Proxies: %s", redact(msal_proxies, name="proxies"))
         if certificate_path or certificate_data:
             return CertificateCredential(
                 tenant_id=tenant_id,
diff --git 
a/providers/microsoft/azure/tests/unit/microsoft/azure/hooks/test_msgraph.py 
b/providers/microsoft/azure/tests/unit/microsoft/azure/hooks/test_msgraph.py
index affe190b359..157d75b3230 100644
--- a/providers/microsoft/azure/tests/unit/microsoft/azure/hooks/test_msgraph.py
+++ b/providers/microsoft/azure/tests/unit/microsoft/azure/hooks/test_msgraph.py
@@ -387,6 +387,27 @@ class TestKiotaRequestAdapterHook:
             error_code = 
actual.get_child_node("error").get_child_node("code").get_str_value()
             assert error_code == "TenantThrottleThresholdExceeded"
 
+    @pytest.mark.asyncio
+    async def test_build_request_adapter_masks_secrets(self):
+        """Test that sensitive data is masked when building request adapter."""
+        with patch(
+            f"{BASEHOOK_PATCH_PATH}.get_connection",
+            side_effect=lambda conn_id: get_airflow_connection(
+                conn_id=conn_id,
+                password="my_secret_password",
+                proxies={"http": "http://user:pass@proxy:3128"},
+            ),
+        ):
+            with 
patch("airflow.providers.microsoft.azure.hooks.msgraph.redact") as mock_redact:
+                mock_redact.side_effect = lambda x, name=None: "***" if x else 
x
+
+                hook = KiotaRequestAdapterHook(conn_id="msgraph_api")
+                await hook.get_async_conn()
+
+                assert mock_redact.call_count >= 3
+                mock_redact.assert_any_call({"http": 
"http://user:pass@proxy:3128"}, name="proxies")
+                mock_redact.assert_any_call("my_secret_password", 
name="client_secret")
+
 
 class TestResponseHandler:
     def test_default_response_handler_when_json(self):
diff --git 
a/shared/secrets_masker/src/airflow_shared/secrets_masker/secrets_masker.py 
b/shared/secrets_masker/src/airflow_shared/secrets_masker/secrets_masker.py
index 5b7ff4e1c81..c78e39ca65a 100644
--- a/shared/secrets_masker/src/airflow_shared/secrets_masker/secrets_masker.py
+++ b/shared/secrets_masker/src/airflow_shared/secrets_masker/secrets_masker.py
@@ -58,6 +58,8 @@ DEFAULT_SENSITIVE_FIELDS = frozenset(
         "passwd",
         "password",
         "private_key",
+        "proxy",
+        "proxies",
         "secret",
         "token",
         "keyfile_dict",
diff --git a/task-sdk/src/airflow/sdk/log.py b/task-sdk/src/airflow/sdk/log.py
index 6e81a96b254..1ee7b1ed1f0 100644
--- a/task-sdk/src/airflow/sdk/log.py
+++ b/task-sdk/src/airflow/sdk/log.py
@@ -36,12 +36,10 @@ if TYPE_CHECKING:
     from airflow.sdk.types import Logger, RuntimeTaskInstanceProtocol as 
RuntimeTI
 
 
-__all__ = ["configure_logging", "reset_logging", "mask_secret"]
+from airflow.sdk._shared.secrets_masker import redact
 
 
 def mask_logs(logger: Any, method_name: str, event_dict: EventDict) -> 
EventDict:
-    from airflow.sdk._shared.secrets_masker import redact
-
     event_dict = redact(event_dict)  # type: ignore[assignment]
     return event_dict
 

Reply via email to