Skip to content

fix(webhook): constant-time signature verification (close timing side-channel)#171

Merged
liplus-lin-lay merged 1 commit into
mainfrom
167-bugwebhook-verifygithubsignature-uses-non-constant-time-string-comparison
Jun 21, 2026
Merged

fix(webhook): constant-time signature verification (close timing side-channel)#171
liplus-lin-lay merged 1 commit into
mainfrom
167-bugwebhook-verifygithubsignature-uses-non-constant-time-string-comparison

Conversation

@liplus-lin-lay

Copy link
Copy Markdown
Member

概要

src/webhook.tsverifyGitHubSignature定数時間比較に修正(#167)。

旧実装は HMAC を再計算して expected === signature で文字列比較していた。=== は最初の不一致で早期終了するため、「先頭が何文字一致したか」が応答時間に滲み、理論上は署名を1バイトずつ当てる timing attack に晒される(タイミング側チャネル)。

変更

  • crypto.subtle.verify("HMAC", ...) に置換。verify は HMAC を再計算して定数時間で比較するので、時間から情報が漏れない。
  • 署名は事前に形式検証(sha256= prefix + 64 hex)。malformed は crypto に触れる前に一律 false。
  • 挙動は不変(正しい署名→true / 不正・malformed→false)。webhook.test.ts の既存契約はそのまま green、non-hex ケースを1件追加。

影響範囲

  • src/webhook.ts(worker 側)のみ。npm パッケージ(mcp-server/)は不変。修正は merge 時の Workers Builds で本番 Worker にデプロイされる。
  • severity 低(ネットワークジッタ支配で実攻撃は非現実的)だが、セキュリティ境界のベストプラクティス遵守。挙動変更なし → patch。

Closes #167

…verify

verifyGitHubSignature recomputed the HMAC and string-compared it with `===`,
which early-exits on the first mismatched character and leaks the expected
signature through response timing (#167). Switch to crypto.subtle.verify, which
recomputes and compares in constant time. Malformed input (bad prefix / wrong
length / non-hex) is rejected up front. Behavior is unchanged (valid -> true,
invalid -> false), so webhook.test.ts stays green; a non-hex case was added.

webhook 署名検証を `===` から定数時間の crypto.subtle.verify に置換し、タイミング
側チャネル(#167)を塞いだ。挙動は不変。

Closes #167
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
github-rag-mcp c8d70a1 Jun 21 2026, 03:20 AM

@liplus-lin-lay liplus-lin-lay left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI セルフレビュー (auto mode)

  • ✅ CI 全 green: test(node 42 + workers 15)+ tsc --noEmit + wrangler dry-run + Workers Builds。ローカルでも確認済み。
  • ✅ 修正は src/webhook.tsverifyGitHubSignature のみ。crypto.subtle.verify による定数時間比較に置換し、=== のタイミング側チャネルを除去。
  • ✅ 挙動不変: webhook.test.ts の契約(valid→true / 不正・malformed→false)はそのまま green、non-hex ケース1件追加。
  • ✅ malformed 署名は crypto に触れる前に形式検証(prefix + 64 hex)で一律 false。
  • リリース種別: 挙動変更なし → patch。

self-review pass。auto mode のため squash merge → #167 close。merge 時の Workers Builds で本番 Worker に定数時間版がデプロイされる。

@liplus-lin-lay liplus-lin-lay merged commit c06edb7 into main Jun 21, 2026
3 checks passed
@liplus-lin-lay liplus-lin-lay deleted the 167-bugwebhook-verifygithubsignature-uses-non-constant-time-string-comparison branch June 21, 2026 03:21
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.

bug(webhook): verifyGitHubSignature uses non-constant-time string comparison

1 participant