Skip to content

[WRONG BRANCH] fix(routing): bound reasoning effort hydration - #34

Draft
luvs01 wants to merge 1 commit into
mainfrom
codex/propose-fix-for-unbounded-reasoningefforts-scan
Draft

[WRONG BRANCH] fix(routing): bound reasoning effort hydration#34
luvs01 wants to merge 1 commit into
mainfrom
codex/propose-fix-for-unbounded-reasoningefforts-scan

Conversation

@luvs01

@luvs01 luvs01 commented Aug 7, 2026

Copy link
Copy Markdown
Owner

Motivation

  • A guard in parseCapability validated only raw.reasoningEfforts.slice(0, 8) but then ran some() and slicing on the original raw.reasoningEfforts, allowing a malicious/Corrupt persisted row to force an unbounded scan and CPU exhaustion.
  • The change aims to ensure normalization only inspects the retained, bounded slice so oversized or mixed arrays cannot drive linear scans of attacker-controlled length.

Description

  • In src/routing/trace.ts parseCapability now reads raw.reasoningEfforts once into a local reasoningEfforts slice (.slice(0, 8)) and performs validation, length checks, and normalization only on that slice.
  • String-length checks for reasoningEfforts now run against the retained slice so caps.strings is set correctly without scanning the original array.
  • Added a regression test in tests/route-decision-trace.test.ts that constructs a very large reasoningEfforts array with a throwing accessor outside the retained range to assert that normalization does not inspect discarded entries.

Testing

  • Ran bun run typecheck and it completed successfully.
  • Ran bun run privacy:scan and it completed successfully.
  • Performed repository checks (git diff --check) and the diff is clean.
  • Attempted to run the focused test file with the local runner (bun scripts/test.ts tests/route-decision-trace.test.ts), but execution failed in this environment due to a runtime mismatch (node:zlib export zstdDecompressSync not available in the installed Bun version); the new regression test is included in the tree and is expected to run in CI (which uses the pinned Bun runtime).

Summary by CodeRabbit

  • Bug Fixes

    • Improved handling of reasoning-effort settings by limiting entries to the first eight.
    • Ensured retained entries are validated, truncated when necessary, and safely normalized.
    • Prevented invalid entries beyond the supported limit from affecting processing.
  • Tests

    • Added coverage confirming the eight-entry limit and normalization behavior.

@github-actions github-actions Bot changed the title fix(routing): bound reasoning effort hydration [WRONG BRANCH] fix(routing): bound reasoning effort hydration Aug 7, 2026
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown

⏳ DRAFT

  • wrong target branch (main); retarget to dev.

What to do

  • Retarget this PR to dev — all contributions go to dev.

Its title has been prefixed with [WRONG BRANCH].
This pull request was already a draft. Its draft status will be preserved after every issue above is resolved.

@github-actions
github-actions Bot marked this pull request as draft August 7, 2026 06:35
@github-actions github-actions Bot added the bug Something isn't working label Aug 7, 2026
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown

Deterministic PR hygiene checks passed.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

parseCapability now inspects only the first eight reasoning-effort entries, validates their types, records truncation, and caps each retained value. A test verifies that entries beyond the retained range are not evaluated.

Changes

Reasoning Effort Normalization

Layer / File(s) Summary
Bounded reasoning-effort parsing
src/routing/trace.ts, tests/route-decision-trace.test.ts
parseCapability normalizes only the first eight entries, validates strings, records oversized values, and truncates retained values. The test verifies that out-of-range accessors are not inspected.

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

Suggested reviewers: wibias, ingwannu

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: bounding reasoning-effort hydration in routing.
✨ 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-unbounded-reasoningefforts-scan

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/routing/trace.ts`:
- Around line 468-475: Update the reasoningEfforts normalization in the trace
parsing flow to reject sparse arrays within the retained first eight entries,
rather than relying on every() and map() which skip and preserve holes. Use an
indexed validation loop or densify the slice before the existing string checks,
and add a regression test covering a sparse reasoningEfforts array.
🪄 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: edb71c19-c108-455c-9cb6-c96c5f7fbfd2

📥 Commits

Reviewing files that changed from the base of the PR and between 2468502 and c3eeaa7.

📒 Files selected for processing (2)
  • src/routing/trace.ts
  • tests/route-decision-trace.test.ts

Comment thread src/routing/trace.ts
Comment on lines +468 to +475
const reasoningEfforts = Array.isArray(raw.reasoningEfforts)
? raw.reasoningEfforts.slice(0, 8)
: undefined;
if (reasoningEfforts
&& reasoningEfforts.every((value): value is string => typeof value === "string")) {
if (reasoningEfforts.some((value: unknown) => typeof value === "string"
&& value.length > MAX_TRACE_STRING)) caps.strings = true;
out.reasoningEfforts = raw.reasoningEfforts
.slice(0, 8)
.map(value => value.slice(0, MAX_TRACE_STRING));
out.reasoningEfforts = reasoningEfforts.map(value => value.slice(0, MAX_TRACE_STRING));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

bun -e '
const sparse = new Array(8);
const mapped = sparse.map(value => value);

if (!sparse.every(value => typeof value === "string")) {
  throw new Error("every() did not skip sparse holes");
}
if (0 in mapped) {
  throw new Error("map() did not preserve sparse holes");
}
'

Repository: luvs01/opencodex

Length of output: 195


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- target file ---'
sed -n '430,500p' src/routing/trace.ts

printf '%s\n' '--- declarations and consumers ---'
rg -n -C 3 'reasoningEfforts|MAX_TRACE_STRING' src test tests 2>/dev/null || true

printf '%s\n' '--- runtime sparse-array semantics ---'
node - <<'JS'
const sparse = new Array(8);
const sliced = sparse.slice(0, 8);
const mapped = sliced.map(value => value);
const densified = Array.from(sliced);

console.log(JSON.stringify({
  every: sliced.every(value => typeof value === "string"),
  mappedHasIndex0: 0 in mapped,
  densifiedHasIndex0: 0 in densified,
  densifiedEvery: densified.every(value => typeof value === "string"),
}));
JS

Repository: luvs01/opencodex

Length of output: 50372


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- exact parser context ---'
sed -n '1,80p' src/routing/trace.ts
sed -n '455,485p' src/routing/trace.ts

printf '%s\n' '--- trace-related tests and parser callers ---'
rg -n -C 4 'parseCapability|reasoningEfforts|trace' tests src/routing/trace.ts \
  -g '*trace*' -g '*routing*' -g '*.test.ts' | head -n 240

printf '%s\n' '--- standalone sparse-array probe ---'
node - <<'JS'
const sparse = new Array(8);
const sliced = sparse.slice(0, 8);
const mapped = sliced.map(value => value);
const densified = Array.from(sliced);

console.log({
  everyAcceptsSparse: sliced.every(value => typeof value === "string"),
  mappedHasIndex0: 0 in mapped,
  densifiedHasIndex0: 0 in densified,
  densifiedEveryAccepts: densified.every(value => typeof value === "string"),
});
JS

Repository: luvs01/opencodex

Length of output: 21731


Reject sparse retained arrays before normalization.

At src/routing/trace.ts:468-475, every() skips holes and map() preserves them. A sparse array in the retained first eight entries therefore passes validation and remains a sparse string[]. Reject the holes with an indexed loop or densify the slice before validation. Add a sparse-array regression test.

Proposed localized fix
 const reasoningEfforts = Array.isArray(raw.reasoningEfforts)
-  ? raw.reasoningEfforts.slice(0, 8)
+  ? Array.from(raw.reasoningEfforts.slice(0, 8))
   : undefined;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const reasoningEfforts = Array.isArray(raw.reasoningEfforts)
? raw.reasoningEfforts.slice(0, 8)
: undefined;
if (reasoningEfforts
&& reasoningEfforts.every((value): value is string => typeof value === "string")) {
if (reasoningEfforts.some((value: unknown) => typeof value === "string"
&& value.length > MAX_TRACE_STRING)) caps.strings = true;
out.reasoningEfforts = raw.reasoningEfforts
.slice(0, 8)
.map(value => value.slice(0, MAX_TRACE_STRING));
out.reasoningEfforts = reasoningEfforts.map(value => value.slice(0, MAX_TRACE_STRING));
const reasoningEfforts = Array.isArray(raw.reasoningEfforts)
? Array.from(raw.reasoningEfforts.slice(0, 8))
: undefined;
if (reasoningEfforts
&& reasoningEfforts.every((value): value is string => typeof value === "string")) {
if (reasoningEfforts.some((value: unknown) => typeof value === "string"
&& value.length > MAX_TRACE_STRING)) caps.strings = true;
out.reasoningEfforts = reasoningEfforts.map(value => value.slice(0, MAX_TRACE_STRING));
🤖 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/routing/trace.ts` around lines 468 - 475, Update the reasoningEfforts
normalization in the trace parsing flow to reject sparse arrays within the
retained first eight entries, rather than relying on every() and map() which
skip and preserve holes. Use an indexed validation loop or densify the slice
before the existing string checks, and add a regression test covering a sparse
reasoningEfforts array.

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

Labels

aardvark bug Something isn't working codex

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant