Skip to content

fix(qa-channel): bound QA bus JSON response reads#99169

Merged
sallyom merged 1 commit into
openclaw:mainfrom
hugenshen:fix/bound-qa-channel-bus-json-responses
Jul 6, 2026
Merged

fix(qa-channel): bound QA bus JSON response reads#99169
sallyom merged 1 commit into
openclaw:mainfrom
hugenshen:fix/bound-qa-channel-bus-json-responses

Conversation

@hugenshen

Copy link
Copy Markdown
Contributor

What Problem This Solves

extensions/qa-channel/src/bus-client.ts used unbounded JSON reads on the QA bus
HTTP success paths:

  • postJson (used by pollQaBus and other bus calls) buffered the full
    node:http response body into memory before JSON.parse.
  • getQaBusState used unbounded await response.json() on the fetch success path.

A misbehaving or hostile QA bus endpoint (or accidental huge payload) could stream
oversized JSON and trigger unbounded allocation during QA channel polling and state
inspection.

This change caps both paths at 16 MiB with labeled errors such as
qa-bus /v1/poll: JSON response exceeds 16777216 bytes and
qa-channel.bus-state: JSON response exceeds 16777216 bytes.

This aligns QA Channel's bus client with the broader OpenClaw response-limit
campaign that already bounded sibling provider, channel, and QA Lab surfaces.

Changes

  • extensions/qa-channel/src/bus-client.ts:

    • adds readQaBusNodeJsonResponse using readByteStreamWithLimit for
      node:http POST responses (pollQaBus, etc.)
    • replaces unbounded response.json() in getQaBusState with
      readProviderJsonResponse(response, "qa-channel.bus-state")
    • normalizes malformed JSON errors to "qa-bus <path>: malformed JSON response"
  • extensions/qa-channel/src/bus-client.test.ts:

    • adds regression tests for oversized /v1/poll and /v1/state responses
    • updates malformed JSON assertion to match the new labeled error
  • scripts/proof-qa-channel-bus-bound.mjs:

    • path-level proof over node:http streaming poll bodies and fetch state reads

Real behavior proof

Behavior addressed: Oversized QA bus JSON success bodies fail closed instead of
unbounded heap growth on poll and state reads.

Real environment tested: Node v22.22.0, macOS 15.3.1, node:http streaming
server on 127.0.0.1, built helpers from dist/plugin-sdk/provider-http.js and
dist/plugin-sdk/response-limit-runtime.js.

Exact steps:

  1. Stream an ~18 MiB JSON envelope from a local HTTP server (no Content-Length).
  2. Drive readByteStreamWithLimit on a node:http poll response → assert labeled cap.
  3. Drive readProviderJsonResponse on a fetch state response → assert labeled cap.
  4. Verify a normal state snapshot still parses.
  5. Run qa-channel vitest regression tests for poll/state bounds.

Observed result:

  • Poll path: qa-bus /v1/poll: JSON response exceeds 16777216 bytes
  • State path: qa-channel.bus-state: JSON response exceeds 16777216 bytes
  • Normal state snapshot parses with accounts and threads arrays intact
  • Vitest: 6 passed (6)
  • ALL PROOF ASSERTIONS PASSED

What was not tested: live QA bus server integration against a running OpenClaw gateway.

Evidence

=== QA Channel bus bound proof (path-level) ===
--- Case 1: node:http poll path rejects oversized streamed body ---
  ok: readByteStreamWithLimit rejects oversized poll stream
  ok: poll label present (got: qa-bus /v1/poll: JSON response exceeds 16777216 bytes)

--- Case 2: fetch state path rejects oversized streamed body ---
  ok: readProviderJsonResponse rejects oversized state stream
  ok: state label present (got: qa-channel.bus-state: JSON response exceeds 16777216 bytes)

--- Case 3: normal state snapshot still parses ---
  ok: state snapshot parses
  ok: threads array intact

--- Case 4: qa-channel bus-client regression tests ---
  Tests  6 passed (6)
  ok: vitest qa-channel bus bound regression tests passed

ALL PROOF ASSERTIONS PASSED
OPENCLAW_VITEST_MAX_WORKERS=1 pnpm test extensions/qa-channel/src/bus-client.test.ts
# Tests  6 passed (6)

New bound regression tests (2 added):

  • bounds oversized poll responses and closes the stream early
  • bounds oversized qa-bus state responses

@openclaw-barnacle openclaw-barnacle Bot added scripts Repository scripts channel: qa-channel Channel integration: qa-channel size: M labels Jul 2, 2026
@clawsweeper

clawsweeper Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 4, 2026, 10:54 PM ET / 02:54 UTC.

Summary
The PR caps QA channel bus JSON success-body reads for node:http POST calls and fetch state reads at 16 MiB, with oversized-response regression tests.

PR surface: Source +18, Tests +116. Total +134 across 2 files.

Reproducibility: yes. Current main clearly buffers node:http QA bus POST responses and uses unbounded response.json() for state, while the PR body supplies a concrete local streaming-server proof; I did not run commands because this review is read-only.

Review metrics: 1 noteworthy metric.

  • QA bus JSON caps: 2 success read paths capped at 16 MiB. postJson covers poll/action POSTs and getQaBusState covers state inspection, so maintainers should notice the new fail-closed payload contract before merge.

Stored data model
Persistent data-model change detected: serialized state: extensions/qa-channel/src/bus-client.test.ts, serialized state: extensions/qa-channel/src/bus-client.ts. Confirm migration or upgrade compatibility proof before merge.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P2] Maintainers should explicitly accept the 16 MiB QA bus response cap or request a QA-specific limit before merge.

Risk before merge

  • [P1] The new 16 MiB cap intentionally makes oversized QA bus poll/action/state success responses fail closed; if a legitimate QA scenario exceeds that size, gateway polling or state inspection will error instead of buffering it.
  • [P1] The contributor proof is path-level with a local streaming node:http server and focused tests, not a live OpenClaw gateway plus QA bus run.

Maintainer options:

  1. Accept the QA bus cap (recommended)
    Merge after ordinary gates if maintainers agree QA bus success bodies over 16 MiB are invalid and should fail closed to protect runtime memory.
  2. Tune the limit before merge
    If legitimate QA bus snapshots can exceed 16 MiB, change to a maintainer-approved QA-specific limit and update the oversized poll/state tests to match.
  3. Pause for live QA proof
    If the payload-size contract is uncertain, hold the PR until a live gateway and QA bus run demonstrates normal polling and state inspection under realistic data volume.

Next step before merge

  • [P1] Maintainer review should decide whether the 16 MiB fail-closed QA bus response cap is acceptable; there is no narrow automated repair unless maintainers choose a different limit.

Security
Cleared: No supply-chain or security regression found; the diff reuses existing SDK response-limit helpers and changes only QA channel source and tests, with no dependency, workflow, secret, or package metadata changes.

Review details

Best possible solution:

Merge this bounded-reader shape if maintainers accept 16 MiB as the QA bus success-body contract; otherwise choose a named QA-specific limit and keep the same poll/state regression coverage aligned.

Do we have a high-confidence way to reproduce the issue?

Yes. Current main clearly buffers node:http QA bus POST responses and uses unbounded response.json() for state, while the PR body supplies a concrete local streaming-server proof; I did not run commands because this review is read-only.

Is this the best way to solve the issue?

Yes, conditionally. The patch is the narrow maintainable fix because it reuses existing bounded-response helpers and adds only a local node:http adapter, but the 16 MiB fail-closed contract still needs maintainer acceptance.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against b34c188f8f0d.

Label changes

Label justifications:

  • P2: This is a normal-priority QA channel availability hardening change with limited blast radius and focused regression coverage.
  • merge-risk: 🚨 availability: Merging the PR can make oversized but previously buffered QA bus success responses fail closed during poll, action, or state reads.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The PR body includes after-fix terminal output from a local node:http streaming proof plus focused qa-channel tests showing oversized poll and state JSON responses reject at the cap while normal state still parses.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes after-fix terminal output from a local node:http streaming proof plus focused qa-channel tests showing oversized poll and state JSON responses reject at the cap while normal state still parses.
Evidence reviewed

PR surface:

Source +18, Tests +116. Total +134 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 1 39 21 +18
Tests 1 118 2 +116
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 2 157 23 +134

What I checked:

Likely related people:

  • steipete: Path history shows the QA channel foundation introduced the bus client and related gateway surface in commit b58f9c5, with later nearby extension documentation touches. (role: introduced feature and adjacent owner; confidence: high; commits: b58f9c52580d, 4fa5092cdc39; files: extensions/qa-channel/src/bus-client.ts, extensions/qa-channel/src/gateway.ts)
  • vincentkoc: Recent QA channel commits touched aborted bus polls, poll failure status, and QA bus trace exposure near the affected polling and state-inspection surface. (role: recent area contributor; confidence: high; commits: 9008031e96e3, 45d7167ea2cc, 9b62a3576078; files: extensions/qa-channel/src/bus-client.ts, extensions/qa-channel/src/gateway.ts)
  • RomneyDa: Recent work consolidated bounded HTTP body helpers and touched QA transport proof paths adjacent to this response-limit hardening. (role: recent adjacent contributor; confidence: medium; commits: 6c53dfa1df99, e701dc76b060; files: src/agents/provider-http-errors.ts, packages/media-core/src/read-byte-stream-with-limit.ts, extensions/qa-channel/src/gateway.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (3 earlier review cycles)
  • reviewed 2026-07-03T13:05:36.141Z sha b43e609 :: needs maintainer review before merge. :: none
  • reviewed 2026-07-04T16:38:02.191Z sha 6f83858 :: needs maintainer review before merge. :: none
  • reviewed 2026-07-05T02:34:11.147Z sha d31eba2 :: needs maintainer review before merge. :: none

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Jul 2, 2026
@hugenshen
hugenshen force-pushed the fix/bound-qa-channel-bus-json-responses branch 2 times, most recently from b43e609 to 6f83858 Compare July 4, 2026 16:32
@openclaw-barnacle openclaw-barnacle Bot added size: S and removed scripts Repository scripts size: M labels Jul 4, 2026
@clawsweeper clawsweeper Bot removed proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jul 4, 2026
@hugenshen
hugenshen force-pushed the fix/bound-qa-channel-bus-json-responses branch from 6f83858 to f07d612 Compare July 5, 2026 02:17
@hugenshen
hugenshen force-pushed the fix/bound-qa-channel-bus-json-responses branch from f07d612 to d31eba2 Compare July 5, 2026 02:28
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. labels Jul 5, 2026
@sallyom

sallyom commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Merge-ready from local maintainer review. Autoreview is clean at head SHA d31eba2, CI is green, and I found no compatibility concerns or breaking changes. This is the best narrow fix for the QA bus JSON parse-boundary gap: it applies the existing 16 MiB JSON cap to the owning bus response read paths while preserving normal QA channel behavior.

@sallyom
sallyom merged commit db334b3 into openclaw:main Jul 6, 2026
121 of 127 checks passed
@sallyom sallyom self-assigned this Jul 6, 2026
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 7, 2026
giodl73-repo pushed a commit to giodl73-repo/openclaw that referenced this pull request Jul 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: qa-channel Channel integration: qa-channel merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. P2 Normal backlog priority with limited blast radius. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: S status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants