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

jscheffl pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new b3138e2400e Fix DiscordWebhookHook leaking webhook_endpoint as HTTP 
header (#65736)
b3138e2400e is described below

commit b3138e2400eeed96863c9ced3ff2ff3e0ad7a519
Author: Sadha Chilukoori <[email protected]>
AuthorDate: Tue Apr 28 11:54:10 2026 -0700

    Fix DiscordWebhookHook leaking webhook_endpoint as HTTP header (#65736)
    
    HttpHook._configure_session_from_extra promotes all unrecognised extra
    connection fields to session headers. The Discord connection stores
    webhook_endpoint in extra, so it was being sent as an HTTP request
    header on every call, causing Discord to return 400 Bad Request.
    
    Override get_conn() in DiscordWebhookHook to strip webhook_endpoint
    from the session headers after the parent builds the session.
    
    Closes #65279
    
    Co-authored-by: Sadha Chilukoori <[email protected]>
---
 .../src/airflow/providers/discord/hooks/discord_webhook.py     | 10 ++++++++++
 .../discord/tests/unit/discord/hooks/test_discord_webhook.py   |  6 ++++++
 2 files changed, 16 insertions(+)

diff --git 
a/providers/discord/src/airflow/providers/discord/hooks/discord_webhook.py 
b/providers/discord/src/airflow/providers/discord/hooks/discord_webhook.py
index a29c7327012..fc2105b377f 100644
--- a/providers/discord/src/airflow/providers/discord/hooks/discord_webhook.py
+++ b/providers/discord/src/airflow/providers/discord/hooks/discord_webhook.py
@@ -27,6 +27,8 @@ from airflow.providers.common.compat.connection import 
get_async_connection
 from airflow.providers.http.hooks.http import HttpAsyncHook, HttpHook
 
 if TYPE_CHECKING:
+    from requests import Session
+
     from airflow.providers.common.compat.sdk import Connection
     from airflow.providers.discord.notifications.embed import Embed
 
@@ -218,6 +220,14 @@ class DiscordWebhookHook(HttpHook):
             conn = self.get_connection(http_conn_id)
         return self.handler.get_webhook_endpoint(conn, webhook_endpoint)
 
+    def get_conn(
+        self, headers: dict[Any, Any] | None = None, extra_options: dict[str, 
Any] | None = None
+    ) -> Session:
+        session = super().get_conn(headers=headers, 
extra_options=extra_options)
+        # HttpHook promotes leftover extra fields to headers; strip the 
Discord-specific one.
+        session.headers.pop("webhook_endpoint", None)
+        return session
+
     def execute(self) -> None:
         """Execute the Discord webhook call."""
         proxies = {}
diff --git a/providers/discord/tests/unit/discord/hooks/test_discord_webhook.py 
b/providers/discord/tests/unit/discord/hooks/test_discord_webhook.py
index e644d23f249..3cf82c7f113 100644
--- a/providers/discord/tests/unit/discord/hooks/test_discord_webhook.py
+++ b/providers/discord/tests/unit/discord/hooks/test_discord_webhook.py
@@ -204,6 +204,12 @@ class TestDiscordWebhookHook:
         # Then
         assert webhook_endpoint == expected_webhook_endpoint
 
+    def test_get_conn_does_not_leak_webhook_endpoint_as_header(self):
+        """webhook_endpoint in connection extra must not be sent as an HTTP 
header to Discord."""
+        hook = DiscordWebhookHook(http_conn_id="default-discord-webhook")
+        session = hook.get_conn()
+        assert "webhook_endpoint" not in session.headers
+
 
 class TestDiscordWebhookAsyncHook:
     @pytest.fixture(autouse=True)

Reply via email to