Conversation
The Hermes webhook adapter's _validate_signature() has no branch for
Pocket's X-HeyPocket-Signature header, so Pocket webhook deliveries
cannot be authenticated via HMAC. Pocket signs the raw request body
with HMAC-SHA256 of "{timestamp}.{body}" using a per-webhook signing
secret and sends the result in X-HeyPocket-Signature, with the
millisecond-resolution timestamp in X-HeyPocket-Timestamp.
Because the adapter's _validate_signature() has no branch for that
header name, any Pocket route with a real secret configured is rejected
as "no recognized signature header" — forcing users to run Pocket
webhooks with INSECURE_NO_AUTH (unauthenticated) or not use Pocket
webhooks at all.
The algorithm Pocket uses is already implemented in the adapter
(generic HMAC-SHA256, hex-encoded); the gap is the missing header-name
branch plus the ms-resolution timestamp (the existing generic V2
scheme uses second-resolution).
Adds a Pocket branch between the GitHub and GitLab branches:
- Reads X-HeyPocket-Signature + X-HeyPocket-Timestamp
- Enforces a 300s replay window on the millisecond timestamp
(same window as generic V2)
- Rejects on missing/malformed/stale timestamp rather than falling
through to a less-protected scheme (mirrors the V2 downgrade guard)
- Compares with _hmac_str_equal for timing-safe comparison
Docs: https://docs.heypocketai.com/docs/api/webhooks
Same pattern as the Linear branch added in NousResearch#87348.
Co-authored-by: Minh Nguyen <menhguin@users.noreply.github.com>
Overall: clean, correctly-scoped addition following the existing per-provider dispatch pattern — constant-time compare via
The fail-closed behavior on absent/unparseable timestamps is right, and placing the branch before the plain-token GitLab check avoids ambiguity since the header names are provider-specific. |
Problem
The Hermes webhook adapter's
_validate_signature()has no branch for Pocket'sX-HeyPocket-Signatureheader, so Pocket webhook deliveries cannot be authenticated via HMAC. Pocket signs the raw request body with HMAC-SHA256 of{timestamp}.{body}using a per-webhook signing secret and sends the result inX-HeyPocket-Signature, with the millisecond-resolution timestamp inX-HeyPocket-Timestamp.Because the adapter's
_validate_signature()has no branch for that header name, any Pocket route with a real secret configured is rejected as "no recognized signature header" — forcing users to run Pocket webhooks withINSECURE_NO_AUTH(unauthenticated) or not use Pocket webhooks at all.The algorithm Pocket uses is already implemented in the adapter (generic HMAC-SHA256, hex-encoded); the gap is the missing header-name branch plus the ms-resolution timestamp (the existing generic V2 scheme uses second-resolution).
Fix
Adds a Pocket branch between the GitHub and GitLab branches in
_validate_signature():X-HeyPocket-Signature+X-HeyPocket-Timestamp_hmac_str_equalfor timing-safe comparisonTesting
pytest tests/gateway/test_webhook_adapter.py)References