Skip to content

[workers] 小さな硬化まとめ (body 上限 / 署名鍵ガード / catch のログ / セキュリティヘッダ) #285

Description

@shinyaoguri

#238 (2026-08 レビューのまとめ Issue) をサブシステム別に分割したうちの workers 分。
項目番号 (w1〜w4) は #238 のトリアージコメントの採番。現存は 2026-08-24 / HEAD d61f126 で再確認済み。

packages/workers/src/checkpoint.ts#226 / #227 とも重なる。着手前に両 Issue の in-flight を確認すること。

w2 — body サイズ上限が sign エンドポイントにしかない

packages/workers/src/index.ts:270 (verify-captcha) / :359 (verify-attestation) / :430 (session/start)

MAX_BODY_BYTES (8 KiB) は checkpoint.ts:65,148,168 = /api/checkpoint/sign だけ。
残る 3 エンドポイントの request.json()無制限で、turnstileToken の長さ検査も無い
(Cloudflare の Turnstile 参考実装は > 2048 を拒否する)。

方針: readJsonBodyLimited() に切り出して 4 エンドポイントで共通化 + token ≤ 2048 + テスト。~30 行

w1 — 署名鍵キャッシュが keyId のみをキーにする

packages/workers/src/checkpoint.ts:99-122

同一 keyId で JWK を差し替えると、isolate が生きている限り旧鍵で署名し続ける。

さらに補足として、registry (packages/shared/src/checkpointKeys/registry.ts:13-30) は
publicKeyJwk.x/y を持つので、同一 keyId で JWK を差し替えると registry の公開鍵と食い違い、
キャッシュの有無に関係なく署名が検証不能になる
。つまり「ローテは必ず keyId 変更を伴う」は
運用ルールではなく不変条件

方針 (推奨: 文書ではなくガード): importKey の前に JWK の x / y を registry と照合し、
不一致なら SIGNING_KEY_MISMATCH で fail-closed にする。~8 行 + テスト + packages/workers/CLAUDE.md に注記 3 行。
決定論的に強制でき、運用ミスをデプロイ直後の 500 で顕在化させられる。

w3 — catch がログなしの汎用 500

packages/workers/src/index.ts:326-341 (handleVerifyCaptcha) / :400-408 (handleVerifyAttestation)

#153session/start は揃えたが、この 2 つに残存 (後者は #238 本文未記載)。
JSON パース失敗も try の中なので 400 ではなく 500 になる。4-6 行

w4 — API 応答にセキュリティヘッダが無い

X-Content-Type-Options: nosniff 等のヒットが 0。純 JSON API なので実害は小さい。
packages/workers/src/index.ts:546-573fetch() が全経路を包むので 1 箇所・~10 行で済む。
cors.test.ts にヘッダの assert を足す。

備考

  • medium 相当: w2 (無制限 body)。low: w1 w3 w4
  • ただし w1 はガードを入れる価値が高い (運用ミスが「署名は成功するが誰も検証できない proof」を生む)

Refs #238 #243

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions