Repository navigation
fix: harden request lifecycle after deep review — crash-safe handlers, byte-safe auth compare, mid-body abort settlement - #7
Merged
Conversation
…te-length safe compare; settle mid-body aborts; NaN timeout fail-fast; keep system role for block-array content
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.
Deep production review of the whole codebase found 5 real issues (all reproduced before fixing):
P1 — route handler promise returned, not awaited
return handleChatCompletions(...)in the createServer callback meant the outertry/catchnever caught handler exceptions: any throw inside an async route handler became an unhandledRejection → process exit. Verified live: a single request crashes the proxy. Also made thefinallyaccess log fire at handler entry, somswas always ~0 (fake duration data). Fix:await handleChatCompletions(...).P1 — auth timingSafeEqual RangeError (single request → crash)
candidate.length === expected.lengthcompares JS string length, buttimingSafeEqualcompares byte length. AnAuthorizationheader with latin1 high bytes of equal string length (e.g.Bearer test-key-1234\xC3) threwERR_CRYPTO_TIMING_SAFE_EQUAL_LENGTH→ with the P1 above, process exit. Reproduced: proxy exited code 1 on one request. Fix: try/catch around the compare (byte-length mismatch = auth failure → 401 + counted toward the rate-limit window).P2 — client aborting mid-body hung the handler forever
req.on('error', () => {})swallowed ECONNRESET whilereadBody's promise never settled → every aborted upload leaked a pending closure and the access log never fired. claude code cancellations mid-upload are a real scenario. Fix: settle on prematureclose/error(req.completeguards the normal path), handleCLIENT_ABORTEDas a silent null (socket is dead, nothing to write).P3 — numeric timeout env garbage → NaN → instant stream aborts
Number(process.env.X || d)yields NaN for garbage;setTimeout(fn, NaN)fires at 0ms → every upstream stream aborts immediately. Added fail-fast validation at boot (refuses to start), matching the module's existing philosophy.P3 — in-messages
systemwith block-array content demoted touserconvertUserBlockshardcodedrole: 'user'; string-content system messages kept their role but array-content ones silently didn't. Fix: pass the caller's role through.Tests
71/71 green (was 67): mid-body abort settlement (log-based hang detector), auth crash regression (401 + process survives), NaN fail-fast (spawn exits 1), system block-array role. Private repo d2567d5 already pushed to main.