Skip to content

fix(webhooks): send signed payload in GET deliveries - #3368

Open
Sanderhoff-alt wants to merge 1 commit into
vectorize-io:mainfrom
Sanderhoff-alt:fix/get-webhook-payload-signature
Open

fix(webhooks): send signed payload in GET deliveries#3368
Sanderhoff-alt wants to merge 1 commit into
vectorize-io:mainfrom
Sanderhoff-alt:fix/get-webhook-payload-signature

Conversation

@Sanderhoff-alt

Copy link
Copy Markdown
Contributor

Context

GET webhook deliveries serialized an event and computed X-Hindsight-Signature over those bytes, but dispatched the request without a body. Receivers therefore observed an empty body, could not parse the event, and could not reproduce the signature from the bytes they received.

Design

  • Keep the serialized event bytes as the single source of truth for both signing and delivery.
  • Dispatch GET webhooks through AsyncClient.request with content=payload_bytes, since the convenience get API does not accept request content.
  • Preserve configured query parameters and the existing POST path.
  • Force Cache-Control: no-cache, no-store for GET deliveries because HTTP caches generally do not include request content in their cache key and could otherwise suppress later events sent to the same URL.
  • Continue routing requests through GuardedAsyncTransport, preserving the existing SSRF validation and IP pinning behavior.

Contract and compatibility

The signature remains sha256=HMAC-SHA256(secret, raw_request_body). Receivers must verify the exact body bytes before parsing JSON; reserialization is not equivalent. POST remains the default and recommended method because GET request bodies are not handled consistently by every server, proxy, or framework. The webhook documentation now makes this limitation explicit.

Verification

  • Added a transport-level regression test using httpx.MockTransport to inspect the final GET method, URL, query parameters, raw body, signature, and cache directive.
  • Added coverage proving GET transport failures enter the existing retry schedule.
  • Ran the complete webhook delivery test class: 7 passed.
  • Ran Ruff checks and formatting checks for the changed Python files.
  • Ran git diff --check.
  • Built the Docusaurus documentation site successfully and regenerated the bundled documentation skill references.

Scope

This change intentionally does not alter POST delivery semantics, webhook persistence, retry timing, signature format, or URL security policy.

GET webhook deliveries signed the serialized event payload but sent no
request body. Receivers therefore saw an empty body that could neither be
parsed nor verified against X-Hindsight-Signature.

Send the exact signed bytes as the GET body and disable caching so a
cached response cannot suppress later events sent to the same URL. Keep
configured query parameters unchanged.

Cover the final httpx transport request, signature verification, query
parameters, cache headers, and GET retry behavior. Document the raw-body
signature contract and the interoperability limits of GET request bodies.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant