fix(ts): return false on truncated webhook signatures - #145
Open
ron-42 wants to merge 1 commit into
Open
Conversation
timingSafeEqual throws RangeError on length mismatch; Python/Rust return false. Malformed traffic can 500 a receiver.
ron-42
requested review from
alex-w-99,
dimavrem22 and
rayruizhiliao
as code owners
August 9, 2026 18:38
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #144
The bug
verifyWebhookcalls Node'stimingSafeEqualwith no length check. WhenX-Inkbox-Signatureissha256=plus a digest that is not exactly 64 hex characters, verification throws:instead of returning
false.Python (
hmac.compare_digest) and Rust (explicit length guard) already returnfalse. A TypeScript webhook receiver that treatsverifyWebhookas a boolean check and does not wrap it intry/catchwill 500 on malformed or attack traffic instead of rejecting with 403.Existing tests only covered equal-length failures, so CI stayed green.
The fix
One length guard before
timingSafeEqual, matching Python/Rust. One regression test forsha256=abcd.CLI and any other caller already go through this shared helper — no second patch.
Verification
Manual cases that previously threw now return
false: truncated, empty digest, odd length, too-long. Valid signatures and wrong-but-same-length digests unchanged.