Skip to content

[WRONG BRANCH] fix(server): bound responses body-read timeout - #184

Draft
luvs01 wants to merge 1 commit into
mainfrom
codex/propose-fix-for-dos-vulnerability-l1u44o
Draft

[WRONG BRANCH] fix(server): bound responses body-read timeout#184
luvs01 wants to merge 1 commit into
mainfrom
codex/propose-fix-for-dos-vulnerability-l1u44o

Conversation

@luvs01

@luvs01 luvs01 commented Aug 9, 2026

Copy link
Copy Markdown
Owner

Motivation

  • Prevent disabling Bun's per-request timeout before authentication and full request-body read for POST /v1/responses, which allowed a client that passed admission checks to send a partial large Content-Length and stall the server indefinitely.

Description

  • Add an onRequestBodyRead?: () => void hook to HandleResponsesOptions and invoke it only after the inbound JSON body is fully read and validated in handleResponsesInner (src/server/responses/core.ts).
  • Stop calling disableResponsesRequestTimeout(req, requestServer) immediately on route match and instead pass onRequestBodyRead: () => disableResponsesRequestTimeout(req, requestServer) from the /v1/responses route in src/server/index.ts so the timeout is disabled only after the body parse succeeds.
  • Add a regression test that uses a streaming/partial request body to verify the timeout is not disabled until the full body arrives, and relax the test assertion to accept any 4xx response (tests can run in varied environments) (tests/server-auth.test.ts).
  • Commit message: fix(server): bound responses body read timeout (three files changed: src/server/index.ts, src/server/responses/core.ts, tests/server-auth.test.ts).

Testing

  • Ran focused tests: bun run test -- tests/server-auth.test.ts -t 'responses handler keeps|responses timeout helper' and the targeted tests passed.
  • Ran typecheck: bun run typecheck and it succeeded.
  • Ran privacy scan: bun run privacy:scan and it succeeded.
  • Full suite: a full bun run test was attempted earlier in the environment but unrelated permission/race tests and environment timeouts were observed; those failures are not caused by this change and were not required to validate the focused regression.

Codex Task

Summary by CodeRabbit

  • Bug Fixes
    • Improved request timeout handling for response requests.
    • Timeouts now remain active until the complete request body has been received and parsed, preventing premature timeout changes during incomplete requests.
  • Tests
    • Added coverage for streamed and incomplete request bodies to verify reliable timeout behavior and error handling.

@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown

⚠️ Wrong target branch

This pull request currently targets main, but pull requests must target one of dev.

@luvs01 Please retarget this PR to dev. All contributions go to dev; main receives only release promotions. See our Contributing guide for details. Thanks! 🙏

Its title has been prefixed with [WRONG BRANCH].

This pull request is being kept as a draft automatically. Once every issue above is resolved, it will be marked ready for review again.

@github-actions github-actions Bot changed the title fix(server): bound responses body-read timeout [WRONG BRANCH] fix(server): bound responses body-read timeout Aug 9, 2026
@github-actions
github-actions Bot marked this pull request as draft August 9, 2026 05:07
@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The Responses handler now disables its request timeout after complete request-body parsing. A new callback connects this point to route timeout handling. Tests verify that incomplete bodies keep the timeout active and malformed JSON returns a client error.

Changes

Responses timeout handling

Layer / File(s) Summary
Body-read callback contract and invocation
src/server/responses/core.ts
HandleResponsesOptions now accepts onRequestBodyRead. The handler invokes it after successful request-body decoding and parsing.
Timeout wiring and validation
src/server/index.ts, tests/server-auth.test.ts
The Responses route disables its timeout through onRequestBodyRead. The test verifies delayed callback execution for chunked input and a 4xx response for malformed JSON.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

  • luvs01/opencodex#176: Both changes modify response-body handling and timeout behavior in src/server/responses/core.ts.

Suggested reviewers: lidge-jun, wibias

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: bounding the server responses body-read timeout.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/propose-fix-for-dos-vulnerability-l1u44o

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/server/responses/core.ts`:
- Line 1371: Update the combo request flow around handleComboResponses so
options.onRequestBodyRead?.() is invoked exactly once after validating the
original request body, before returning or dispatching child requests. Remove or
guard onRequestBodyRead when forwarding options to parsed child requests,
preserving the callback behavior for non-combo requests.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d6b48181-c92f-4bc4-9cde-5f8e927edf94

📥 Commits

Reviewing files that changed from the base of the PR and between 8a9c0ef and ee6d2ec.

📒 Files selected for processing (3)
  • src/server/index.ts
  • src/server/responses/core.ts
  • tests/server-auth.test.ts

}
return formatErrorResponse(400, "invalid_request_error", err instanceof Error ? err.message : String(err));
}
options.onRequestBodyRead?.();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

rg -n -C 20 \
  'handleComboResponses|comboIdFromRawBody|comboAttempt|onRequestBodyRead' \
  src/server/responses/core.ts

rg -n -C 10 \
  'onRequestBodyRead|handleResponses\(' \
  src/server/index.ts tests/server-auth.test.ts

Repository: luvs01/opencodex

Length of output: 30248


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- handleComboResponses implementation ---'
sed -n '974,1235p' src/server/responses/core.ts

printf '%s\n' '--- callback gate definition and usages ---'
rg -n -C 20 'createChildPassthroughCallbackGate|onRequestBodyRead' src/server/responses/core.ts

printf '%s\n' '--- combo-related tests and callback assertions ---'
rg -n -C 12 'combo|onRequestBodyRead|timeout' tests src/server | head -n 500

Repository: luvs01/opencodex

Length of output: 50372


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- handleResponses entry and callback propagation ---'
rg -n -C 18 '^export async function handleResponses|onRequestBodyRead' src/server/responses/core.ts

printf '%s\n' '--- focused combo test files ---'
git ls-files 'tests/*' | while IFS= read -r file; do
  if rg -q 'handleComboResponses|comboAttempt|comboIdFromRawBody|combos:' "$file"; then
    printf '%s\n' "$file"
  fi
done

printf '%s\n' '--- callback-related test locations ---'
rg -n -C 8 'onRequestBodyRead' tests src/server/index.ts

Repository: luvs01/opencodex

Length of output: 8382


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

printf '%s\n' '--- timeout callback implementation ---'
rg -n -C 12 'function disableResponsesRequestTimeout|disableResponsesRequestTimeout' src/server

printf '%s\n' '--- combo failover test structure ---'
rg -n -C 8 'describe|test\(|failover|retry|targets' tests/server-combo-failover-e2e.test.ts | head -n 240

printf '%s\n' '--- read-only source verifier ---'
python3 - <<'PY'
from pathlib import Path

source = Path("src/server/responses/core.ts").read_text()
combo_branch = "if (comboId && Object.hasOwn(config.combos ?? {}, comboId)) {\n    return handleComboResponses(req, body, comboId, config, logCtx, options);"
callback_call = "options.onRequestBodyRead?.();"
child_forward = "...options,"
child_guard = "comboAttempt: true,"

assert combo_branch in source
assert callback_call in source
assert source.index(combo_branch) < source.index(callback_call)
combo_start = source.index("export async function handleComboResponses(")
combo_end = source.index("\n\n\nfunction finalizeOwnedTranslatorBudget", combo_start)
combo = source[combo_start:combo_end]
assert child_forward in combo and child_guard in combo
assert callback_call not in combo

print("combo branch returns before the outer callback")
print("combo child forwards the parent options and invokes the shared callback in handleResponsesInner")
print("no combo-specific one-shot guard exists")
PY

Repository: luvs01/opencodex

Length of output: 26032


🏁 Script executed:

#!/usr/bin/env bash
set -u

python3 - <<'PY'
from pathlib import Path

source = Path("src/server/responses/core.ts").read_text()
combo_branch = """if (comboId && Object.hasOwn(config.combos ?? {}, comboId)) {
    return handleComboResponses(req, body, comboId, config, logCtx, options);"""
callback_call = "options.onRequestBodyRead?.();"
combo_start = source.index("export async function handleComboResponses(")
combo_end = source.index("\n\n\nfunction finalizeOwnedTranslatorBudget", combo_start)
combo = source[combo_start:combo_end]

checks = {
    "combo branch returns before outer callback": source.index(combo_branch) < source.index(callback_call),
    "combo forwards parent options to child": "...options," in combo,
    "child marks recursive call as combo attempt": "comboAttempt: true," in combo,
    "combo handler has no direct callback call": callback_call not in combo,
}
for name, value in checks.items():
    print(f"{name}: {value}")
assert all(checks.values())

print("Conclusion: each successfully parsed child reaches the shared callback, so a two-target failover can invoke it twice.")
PY

Repository: luvs01/opencodex

Length of output: 464


Invoke onRequestBodyRead once for the original combo request. In src/server/responses/core.ts:1320-1323, the combo path returns before line 1371. handleComboResponses forwards ...options to each child at lines 1097-1114, so each parsed child invokes the callback. A two-target failover can invoke it twice. Call it once after validating the original body, then omit it from child options or guard it as one-shot.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/server/responses/core.ts` at line 1371, Update the combo request flow
around handleComboResponses so options.onRequestBodyRead?.() is invoked exactly
once after validating the original request body, before returning or dispatching
child requests. Remove or guard onRequestBodyRead when forwarding options to
parsed child requests, preserving the callback behavior for non-combo requests.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant