Describe the bug
There are two issues in controller callbacks:
-
The HMAC signature check uses plain !== string comparison, which can short-circuit on the first mismatched character and leak timing information. The OpenNode callback already handles this correctly with crypto.timingSafeEqual.
-
On signature mismatch, the error log includes the server-computed valid HMAC (expected). Since HMAC is deterministic, anyone with log access could replay the same request body with the leaked signature and pass the check.
OpenNode uses timingSafeEqual, validates input format, and doesn't log the expected value.
Expected behavior
The Nodeless callback should follow the same pattern as OpenNode:
- Use
crypto.timingSafeEqual with Buffer comparison
- Validate the signature header format before comparing
- Only log
actual (what the caller sent), not expected
Describe the bug
There are two issues in controller callbacks:
The HMAC signature check uses plain
!==string comparison, which can short-circuit on the first mismatched character and leak timing information. The OpenNode callback already handles this correctly withcrypto.timingSafeEqual.On signature mismatch, the error log includes the server-computed valid HMAC (
expected). Since HMAC is deterministic, anyone with log access could replay the same request body with the leaked signature and pass the check.OpenNode uses
timingSafeEqual, validates input format, and doesn't log the expected value.Expected behavior
The Nodeless callback should follow the same pattern as OpenNode:
crypto.timingSafeEqualwithBuffercomparisonactual(what the caller sent), notexpected