Skip to content

fix: add HMAC-SHA256 signature for outbound webhook events (PILOT-90)#3

Merged
TeoSlayer merged 1 commit into
mainfrom
openclaw/pilot-90-20260528-044016
May 28, 2026
Merged

fix: add HMAC-SHA256 signature for outbound webhook events (PILOT-90)#3
TeoSlayer merged 1 commit into
mainfrom
openclaw/pilot-90-20260528-044016

Conversation

@matthew-pilot
Copy link
Copy Markdown
Collaborator

What

The webhook Client POSTs unsigned JSON with no integrity or authenticity guarantee. Anyone who can reach the configured URL — MITM, spoofed IP, leaked URL — can forge events the receiver will treat as authentic.

Fix

Add an optional pre-shared secret via WithSecret(secret string) client option. When set, every outbound POST includes an X-Pilot-Signature-256 header containing the hex-encoded HMAC-SHA256 of the request body.

Backward-compatible: receivers that do not care about signatures simply ignore the header.

Files changed

  • webhook.go: Client.secret field, WithSecret() option, HMAC computation in post(), POSThttp.NewRequest + client.Do to inject the header (same send + retry + circuit-breaker semantics)
  • zz_fuzz_webhook_test.go: TestWebhookClientHMACSignatureHeader (secret → header present, validates HMAC) + TestWebhookClientNoSignatureWhenNoSecret (no secret → no header)

Verification

go build ./...  → clean
go vet ./...   → clean
go test ./...  → all tests pass (5.5s)

Closes PILOT-90

The webhook Client POSTs unsigned JSON with no integrity or authenticity
guarantee.  Add an optional pre-shared secret (WithSecret option); when
set, every outbound POST includes an X-Pilot-Signature-256 header with
the hex-encoded HMAC-SHA256 of the request body.

Receivers that do not care about signatures simply ignore the header
(backward-compatible).  Receivers that DO care recompute the HMAC
against the shared secret and reject mismatches.

Changes:
- Client.secret field + WithSecret() option
- crypto/hmac, crypto/sha256, encoding/hex imports
- post() switches from client.Post to http.NewRequest + client.Do to
  inject the header (same send semantics, same retry+circuit-breaker
  logic preserved)

Verification:
- go build ./...  → clean
- go vet ./...   → clean
- All existing tests pass + new TestWebhookClientHMACSignatureHeader
  and TestWebhookClientNoSignatureWhenNoSecret

Closes PILOT-90
@codecov
Copy link
Copy Markdown

codecov Bot commented May 28, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@TeoSlayer TeoSlayer merged commit e3a02e0 into main May 28, 2026
2 checks passed
@TeoSlayer TeoSlayer deleted the openclaw/pilot-90-20260528-044016 branch May 28, 2026 16:57
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.

2 participants