fix(agents): keep extension exec truncation UTF-16 safe#102007
fix(agents): keep extension exec truncation UTF-16 safe#102007mushuiyu886 wants to merge 2 commits into
Conversation
|
Codex review: needs maintainer review before merge. Reviewed July 8, 2026, 2:30 AM ET / 06:30 UTC. Summary PR surface: Source +4, Tests +60. Total +64 across 2 files. Reproducibility: yes. Source inspection shows current Review metrics: none identified. Stored data model Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Next step before merge
Security Review detailsBest possible solution: Land the source-boundary fix after ordinary exact-head review and merge checks; any broader command-output decoding cleanup should stay separate. Do we have a high-confidence way to reproduce the issue? Yes. Source inspection shows current Is this the best way to solve the issue? Yes. Fixing AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against c46e76cff724. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +4, Tests +60. Total +64 across 2 files. View PR surface stats
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
|
|
@clawsweeper automerge |
|
🦞✅ Source: Why human review is needed: What the maintainer can do as a next step: I added |
a7fb763 to
9045105
Compare
|
🦞✅ Source: Why human review is needed: What the maintainer can do as a next step: I added |
Consolidates #102007, #101818, and #101782. Co-authored-by: 杨浩宇0668001029 <[email protected]> Co-authored-by: NIO <[email protected]> Co-authored-by: Cursor <[email protected]>
|
Landed the canonical fix on The valid Proof on the landed patch:
Closing this PR as included in the landed main commit, not rejected. |
Consolidates openclaw#102007, openclaw#101818, and openclaw#101782. Co-authored-by: 杨浩宇0668001029 <[email protected]> Co-authored-by: NIO <[email protected]> Co-authored-by: Cursor <[email protected]>
Consolidates openclaw#102007, openclaw#101818, and openclaw#101782. Co-authored-by: 杨浩宇0668001029 <[email protected]> Co-authored-by: NIO <[email protected]> Co-authored-by: Cursor <[email protected]>
Summary
execretained stdout and stderr UTF-16 safe when output is caller-capped.sliceUtf16Safehelper for both tail-retention and default output-limit truncation.What Problem This Solves
Extension runtime commands can return stdout/stderr containing non-BMP characters such as emoji.
execCommandretained output withString.prototype.slice, so a cap that landed between UTF-16 surrogate halves could return a dangling surrogate in the retained stream.The anchor PR fixed the same class of truncation bug for exec auto-reviewer rationale text. This follow-up applies the same shared UTF-16-safe truncation invariant to extension/custom-tool command output retention.
User Impact
Users running extensions or custom tools that emit emoji or other non-BMP text could receive broken retained stdout/stderr after truncation. That broken text can be surfaced as command output, diagnostics, or model-visible tool output. After this patch, truncation may retain one fewer UTF-16 code unit at a split boundary, but it will not return an invalid surrogate half.
Origin / follow-up
Follows and completes #101513.
src/agents/sessions/exec.tsstill used rawslice()for retained stdout/stderr in the extension/custom-tool command execution path.@openclaw/normalization-core/utf16-slicehelper instead of introducing another truncation implementation.Competition / linked PR analysis
I checked current open PRs and issues for the same
execCommand/ extension exec UTF-16 truncation gap.extension exec output UTF-16 surrogateorexecCommand truncation surrogate.execCommand truncation UTF-16 safe.src/agents/sessions/exec.tsor the extension exec stdout/stderr retention path.Real behavior proof
execCommand→ExecResultruntime object → retained stdout/stderr returned as the command effect.execCommandretention logic used by extension command execution.sliceUtf16Safeis reused; provider-specific constraints are not applicable to this local command-output boundary.appendCapturedOutputis the source-of-truth retention boundary forExecResultstdout/stderr caps. The patch fixes the invariant there instead of adding a downstream cleanup step, so stored/returned command output share the same safe retained text.{ "stdout": "B", "stderr": "D", "stdoutLength": 1, "stderrLength": 1, "stdoutCodes": ["42"], "stderrCodes": ["44"], "stdoutDangling": [], "stderrDangling": [], "stdoutTruncatedChars": 3, "stderrTruncatedChars": 3, "code": 0 }execCommandchild-process output capture path.src/agents/sessions/exec.test.ts.A😀Band stderrC😀DwithmaxOutputChars: 2now retainBandDwithout dangling surrogate halves; the default output-limit path also avoids retaining a half emoji at the cap boundary.execCommandat the retained-output source-of-truth boundary, covers both stdout and stderr, and also covers the default limit path where the same helper is now used.Review findings addressed
No maintainer review findings are attached to this follow-up yet. This patch addresses the sibling gap left by #101513 in the extension exec output retention path.
Regression Test Plan
The regression suite now covers:
Merge risk
src/agents/sessions/exec.tsandsrc/agents/sessions/exec.test.tsonly.Risk / Compatibility
Risk is low and localized to retained output truncation in
execCommand.stdoutTruncatedCharsandstderrTruncatedCharsnow count the actual number of removed UTF-16 code units after safe slicing.What was not changed
Root Cause
execCommandused rawString.prototype.slice()to enforce retained output caps. JavaScript slicing is based on UTF-16 code units, so slicing at a cap boundary can return only one half of a surrogate pair.appendCapturedOutputwith the shared UTF-16-safe helper, covering tail retention for caller-supplied caps and head retention for default output-limit enforcement at the source where retained stdout/stderr is produced.