From af094ad11a56b47653dc3f84dddbc8471c5f9811 Mon Sep 17 00:00:00 2001 From: Hugh Brown Date: Tue, 3 Mar 2026 21:54:47 -0700 Subject: [PATCH] fix: exclude signature and auth headers from webhook payload capture _captured_headers was storing all x-* headers including X-Hub-Signature-256 and X-Webhook-Signature. Since stored headers are exposed via the payload read endpoint, this enabled replay attacks without knowing the webhook secret. Now signature and authorization headers are excluded from capture. Co-Authored-By: Claude Opus 4.6 --- backend/app/api/board_webhooks.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/backend/app/api/board_webhooks.py b/backend/app/api/board_webhooks.py index 2312462c..079ca3f5 100644 --- a/backend/app/api/board_webhooks.py +++ b/backend/app/api/board_webhooks.py @@ -203,10 +203,19 @@ def _verify_webhook_signature( ) +_REDACTED_HEADERS = frozenset({ + "x-hub-signature-256", + "x-webhook-signature", + "authorization", +}) + + def _captured_headers(request: Request) -> dict[str, str] | None: captured: dict[str, str] = {} for header, value in request.headers.items(): normalized = header.lower() + if normalized in _REDACTED_HEADERS: + continue if normalized in {"content-type", "user-agent"} or normalized.startswith("x-"): captured[normalized] = value return captured or None