fix(config): use Object.hasOwn instead of in operator for provider validation#99849
fix(config): use Object.hasOwn instead of in operator for provider validation#99849zenglingbiao wants to merge 4 commits into
Conversation
|
Codex review: needs real behavior proof before merge. Reviewed July 4, 2026, 6:02 AM ET / 10:02 UTC. Summary PR surface: Source +5, Tests +54. Total +59 across 4 files. Reproducibility: yes. source-reproducible: Review metrics: 2 noteworthy metrics.
Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Risk before merge
Maintainer options:
Next step before merge
Security Review findings
Review detailsBest possible solution: Narrow this PR to the Talk config fix by updating both Zod validators and the runtime resolver with matching tests, and either remove the web fallback changes or move a truly bounded version to a separate PR with current-head proof. Do we have a high-confidence way to reproduce the issue? Yes, source-reproducible: Is this the best way to solve the issue? No. The resolver change is necessary, but the best fix must also update the schema validators and avoid bundling the unrelated unbounded web fallback change. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 79d2e568a0aa. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +5, Tests +54. Total +59 across 4 files. View PR surface stats
Security concerns:
What I checked:
Likely related people:
What the crustacean ranks mean
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
Review history (8 earlier review cycles)
|
17e6a10 to
eb69c12
Compare
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
readResponseText's .text() fallback path ignored the maxBytes option, reading the full body unbounded. When a foreign Response lacks a body stream (no getReader) and no arrayBuffer(), the .text() call was the last resort — but maxBytes was never applied. - Honor maxBytes in the .text() fallback: truncate + set truncated=true - Under-cap responses pass through unchanged - No maxBytes set → original behavior preserved (regression safe)
eb69c12 to
79ac2a2
Compare
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
Replace text.length/text.slice (character-level) with TextEncoder/ TextDecoder (byte-level) so the maxBytes cap is respected at byte granularity, consistent with the bounded-stream path at lines 240-298. - bytes.byteLength > maxBytes instead of text.length > maxBytes - TextDecoder().decode(bytes.slice(0, maxBytes)) for byte-safe truncation - bytesRead reports actual bytes, not character count
79ac2a2 to
698c99d
Compare
34ae29c to
97cca0d
Compare
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
97cca0d to
1387ce9
Compare
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
Source: #99849 Co-authored-by: zenglingbiao <[email protected]>
* fix(agents): harden LSP process failures Source: #100450 Co-authored-by: morluto <[email protected]> * fix(sandbox): report effective workspace layout Sources: #100435, #100439 Co-authored-by: Aniruddha Adak <[email protected]> Co-authored-by: ZengWen-DT <[email protected]> * fix(security): fail install checks on stream errors Source: #100413 Co-authored-by: 陈宪彪0668000387 <[email protected]> * fix(android): normalize all-day calendar events Source: #100032 Co-authored-by: NianJiuZst <[email protected]> * fix(ios): serialize push-to-talk lifecycle Source: #99942 Co-authored-by: NianJiuZst <[email protected]> * fix(talk): reject inherited provider names Source: #99849 Co-authored-by: zenglingbiao <[email protected]> * fix(android): stop voice capture in background Source: #99840 Co-authored-by: xialonglee <[email protected]> * fix(cron): preserve fallback result classification Source: #99913 Co-authored-by: jincheng-xydt <[email protected]> * fix(google): bound Vertex response decompression Source: #99812 Co-authored-by: 黄剑雄0668001315 <[email protected]> * fix(plugins): report malformed discovery JSON Source: #99892 Co-authored-by: 陈宪彪0668000387 <[email protected]> * test(sandbox): configure non-default workspace fixture * test: fix small-fix batch validation --------- Co-authored-by: morluto <[email protected]> Co-authored-by: ZengWen-DT <[email protected]> Co-authored-by: 陈宪彪0668000387 <[email protected]> Co-authored-by: NianJiuZst <[email protected]> Co-authored-by: zenglingbiao <[email protected]> Co-authored-by: xialonglee <[email protected]> Co-authored-by: jincheng-xydt <[email protected]> Co-authored-by: 黄剑雄0668001315 <[email protected]>
|
Thanks @zenglingbiao — your prototype-chain provider validation fix was incorporated into #100483, landed as aaf5ab9. The landed version applies own-property checks at all three sibling Talk boundaries and covers both |
* fix(agents): harden LSP process failures Source: openclaw#100450 Co-authored-by: morluto <[email protected]> * fix(sandbox): report effective workspace layout Sources: openclaw#100435, openclaw#100439 Co-authored-by: Aniruddha Adak <[email protected]> Co-authored-by: ZengWen-DT <[email protected]> * fix(security): fail install checks on stream errors Source: openclaw#100413 Co-authored-by: 陈宪彪0668000387 <[email protected]> * fix(android): normalize all-day calendar events Source: openclaw#100032 Co-authored-by: NianJiuZst <[email protected]> * fix(ios): serialize push-to-talk lifecycle Source: openclaw#99942 Co-authored-by: NianJiuZst <[email protected]> * fix(talk): reject inherited provider names Source: openclaw#99849 Co-authored-by: zenglingbiao <[email protected]> * fix(android): stop voice capture in background Source: openclaw#99840 Co-authored-by: xialonglee <[email protected]> * fix(cron): preserve fallback result classification Source: openclaw#99913 Co-authored-by: jincheng-xydt <[email protected]> * fix(google): bound Vertex response decompression Source: openclaw#99812 Co-authored-by: 黄剑雄0668001315 <[email protected]> * fix(plugins): report malformed discovery JSON Source: openclaw#99892 Co-authored-by: 陈宪彪0668000387 <[email protected]> * test(sandbox): configure non-default workspace fixture * test: fix small-fix batch validation --------- Co-authored-by: morluto <[email protected]> Co-authored-by: ZengWen-DT <[email protected]> Co-authored-by: 陈宪彪0668000387 <[email protected]> Co-authored-by: NianJiuZst <[email protected]> Co-authored-by: zenglingbiao <[email protected]> Co-authored-by: xialonglee <[email protected]> Co-authored-by: jincheng-xydt <[email protected]> Co-authored-by: 黄剑雄0668001315 <[email protected]>
Summary
Use
Object.hasOwn()instead of theinoperator inTalkRealtimeSchema,TalkSchemasuperRefine validators, andactiveProviderFromTalkruntime resolver to prevent prototype chain pollution when validating and resolving provider keys.What Problem This Solves
When a user sets
talk.providerortalk.realtime.providerto anObject.prototypekey likeconstructoror__proto__, theinoperator traverses the prototype chain and incorrectly reports the key as present in the providers object — even though no such provider is configured.Consequence:
provider: "constructor"when it should be rejected.activeProviderFromTalkwould incorrectly resolve"constructor"as a valid active provider, returning it as the active provider for downstream config responses.Code evidence:
src/config/zod-schema.ts:329—!(provider in realtime.providers!)in superRefinesrc/config/zod-schema.ts:365—!(provider in talk.providers!)in superRefinesrc/config/talk.ts:160—!(provider in providers)inactiveProviderFromTalkRoot Cause
inoperator checks the entire prototype chain, not just own propertiesObject.hasOwn()(ES2022+) correctly checks only the object's own propertiesObject.hasOwnis already used 30+ times acrosssrc/config/— these three sites were the remaininginoperator usages on plain objects with variable keysWhy This Fix
Object.hasOwnusage pattern throughoutsrc/config/Evidence
provider: "constructor"/provider: "__proto__"→ validation incorrectly passes (prototype keys bypass both schema and resolver)provider: "constructor"/provider: "__proto__"→ validation correctly rejects with "missing" error; runtime resolver returns undefinedReal Behavior Proof
Before (on main)
After (with fix)
Tests and Validation
constructorand__proto__rejection in bothtalk.providerandtalk.realtime.providerbuildTalkConfigResponsewith prototype keys returns no resolved providerpnpm check: passed (only pre-existingnpm shrinkwrap guardfailure, unrelated)