feat: 取得ボディにサイズ上限とタイムアウトを設ける(#56)#61
Conversation
許可ホストでも侵害時に巨大/無限ストリームでメモリ枯渇やハングを招き得るため、
fetch 経路に上限を入れる。
- constants.ts: REQUEST_TIMEOUT_MS(30s) / MAX_RESPONSE_BYTES(16MiB)
- github.ts:
- secureFetch に AbortSignal.timeout を付与(hop + 最終 body 読込をカバー、
タイムアウトは transient で withRetry が再試行)
- readCappedText: Content-Length 事前チェック + ストリームしながらバイト数を
数え、上限超過は PermanentError(再試行しても同じ巨大 body を引くため)。
fetchJson/fetchText が resp.json()/text() の代わりに使用
- tests: size cap(上限内/超過)+ timeout signal の配線を検証
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AECzAv2vcdATecuvLjBSa6
- CLAUDE.md: Reliability core に readCappedText / AbortSignal.timeout を追記 - TODO.md: #56 を解決済み(#61)へ Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AECzAv2vcdATecuvLjBSa6
- github.ts: Content-Length 事前チェックを削除(streaming のバイト数が真の 防御。事前チェックは body を cancel せずソケットリーク[CodeRabbit]、gzip 時に 圧縮長と非圧縮カウントが不整合[opencode]、Number(null) の曖昧さ、と難あり) - github.ts: over-cap の reader.cancel() を .catch(() => undefined) し、cancel の 失敗が PermanentError を masking しないように[opencode] - github.ts: fetchJson で先頭 BOM を除去(resp.json() は除去していたが JSON.parse は失敗=退行)[opencode] - github.ts: readCappedText の "Exported for testing" コメントを実態に修正 - download.ts: preflight の fall-through が TypeError のみで、AbortSignal.timeout の DOMException を取りこぼし #54 の挙動を壊していたため timeout/abort も許容 [opencode]。tool-cache のバイナリ転送が未制限な理由(proxy 維持・job/ディスク backstop・SHA256 検証)をコメント化[codex/altitude] - tests: BOM 除去 / preflight timeout フォールスルー を追加 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AECzAv2vcdATecuvLjBSa6
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (7)
📝 WalkthroughSummary by CodeRabbit
ウォークスルー
変更点NFR-1: タイムアウトとボディサイズ上限の実装
推定コードレビュー労力🎯 3 (Moderate) | ⏱️ ~20 minutes 関連する可能性のある PR
詩
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #61 +/- ##
==========================================
+ Coverage 70.32% 71.80% +1.47%
==========================================
Files 13 13
Lines 246 266 +20
Branches 62 67 +5
==========================================
+ Hits 173 191 +18
- Misses 64 65 +1
- Partials 9 10 +1
🚀 New features to boost your workflow:
|
概要
fetchText/fetchJsonは許可ホストのレスポンスを上限なしで読み切り、per-request タイムアウトも無かった。許可ホストでも侵害時に巨大/無限ストリームでメモリ枯渇やハングを招き得るため、fetch 経路に上限を入れる(#56 / NFR-1)。変更内容
constants.ts:REQUEST_TIMEOUT_MS(30s) /MAX_RESPONSE_BYTES(16 MiB)github.tssecureFetch:AbortSignal.timeoutを全 hop + 最終 body 読込にかける(タイムアウトは transient でwithRetryが再試行)readCappedText: ストリームしながらバイト数を数え、上限超過はPermanentError。fetchJson/fetchTextがresp.json()/resp.text()の代わりに使用fetchJson: 先頭 BOM を除去(resp.json()の挙動を維持)download.ts: preflight の fall-through が timeout(DOMException) も許容するよう拡張。tool-cache のバイナリ転送が未制限な理由(proxy 維持・job/disk backstop・SHA256 検証)をコメント化レビュー(push 前にローカル実施)
CodeRabbit / codex / opencode / comment-analyzer +
/simplify4エージェントで多面レビューし、以下を反映:reader.cancel()を catch(PermanentError の masking 防止)resp.json()退行の修正)検証
pnpm run all✅(typecheck / lint / 79 tests / build)/typos✅ /actionlint✅参照
🤖 Generated with Claude Code
Summary by cubic
Add a per-request timeout and response body size cap to all GitHub fetches to prevent hangs and memory exhaustion from trusted hosts. Applies a 30s timeout and a 16 MiB cap; timeouts are retried, size overruns fail permanently. Closes #56.
New Features
REQUEST_TIMEOUT_MS(30s) andMAX_RESPONSE_BYTES(16 MiB) inconstants.ts.secureFetchnow uses a singleAbortSignal.timeoutacross redirects and body read; retries on timeout viawithRetry.readCappedTextto stream and cap bytes; used byfetchJsonandfetchText.Bug Fixes
fetchJsonstrips a leading BOM beforeJSON.parseto matchresp.json()behavior.download.tsnow falls through onDOMExceptiontimeouts/aborts (still blocks on untrusted hosts).Written for commit e0988c9. Summary will update on new commits.