Repository navigation
fix(sandboxd): escape C0 control chars in JSON so coloured output survives - #669
Merged
Merged
Conversation
…vives sandboxd's jsonEscape handled only five characters: quote, backslash, newline, carriage return and tab. Every other C0 control character was copied through raw — including ESC (0x1B), which is what every terminal program emits for an ANSI colour code. RFC 8259 forbids raw control characters inside a JSON string, so a response carrying coloured output was not valid JSON. The control plane decoded it into an empty struct and swallowed the error, so the caller saw "the run produced no output" while the bytes sat unread in the sandboxd buffer. A background run of a marquee came back as 0 bytes; `k8e-sandbox-cli poll` showed an empty result. jsonEscape is used in seven places — the exec response, files read/list, the process table, the transcript and the background-run stdout/stderr — so any command with colour in its output lost it, and a file containing an ESC byte produced an unparsable body. Escape all of 0...31 as \u00XX, matching the sibling helper in execctl.zig, which already did this. Also stop swallowing the decode error in the Go control plane. A malformed body now surfaces as an error instead of an empty result, so the next malformed response is visible rather than silent. Verified against a marquee over the official E2B SDK path: before: poll -> status="" stdout="" (0 bytes) after: poll -> status=completed stdout=169828 bytes sandboxd: 61/61 tests pass (2 new). Go: 37/37 packages pass.
|
Contributor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



背景
用官方
k8e-sandbox-cli连上远端集群跑一个跑马灯(滚动 ANSI 彩色横幅)时发现:输出完全为空——但命令明明在沙箱里跑了 16 秒、打印了 169 KB 的彩色帧。
根因
sandboxd 的
jsonEscape(sandboxd/src/exec.zig)只转义了 5 个字符:ESC (0x1B) 没有被转义——而它正是所有终端程序输出 ANSI 颜色码的开头。
RFC 8259 禁止 JSON 字符串里出现未转义的控制字符,所以带颜色的响应不是合法 JSON。实测抓到的响应体:
响应体里
\r被正确转义成了\r(2 字符),但 ESC 是原始 0x1B 字节,出现 9145 次。控制面
PollRun把 decode 错误吞掉了:于是调用方看到的是「这个任务没有产生任何输出」,而真实字节还躺在 sandboxd 的缓冲区里。
jsonEscape一共被 7 处使用:exec 响应、files read/list、进程表、transcript、background 的 stdout/stderr。所以任何带颜色的命令输出都会丢,含有 ESC 字节的文件也会产生无法解析的响应体。同一个文件里的兄弟函数
execctl.zig的escapeJson本来就是对的(转义全部0...31)——只有exec.zig这一份漏了。修改
sandboxd/src/exec.zig—jsonEscape把全部0...31转义成\u00XX,与execctl.zig的实现对齐。pkg/sandboxmatrix/grpc/server.go/orchestrator.go— 不再吞掉 decode 错误。新增decodeSandboxdResponse收口,非法响应体以错误形式返回,而不是伪装成「没有输出」。这样下一个出问题的响应会立刻暴露,而不是静默。验证
同一个跑马灯,前后对比:
status="" stdout=""— 0 字节status=completed stdout=169828 字节— 完整 24-bit 彩色帧同步
run路径(exec.zig的 exec 响应)同样修复:影响面
任何输出带 ANSI 颜色码的命令都会受影响——
ls --color、git diff --color、进度条、TUI 程序,以及我们自己的跑马灯。修复前它们的输出会被静默丢弃。关联
K8E 集群:
13.125.242.118(节点ip-172-31-16-11,4C8G,gVisor)k8e 版本:
v1.37.0-20261022-rc1sandbox 镜像:官方
ghcr.io/xiaods/k8e-sandbox@sha256:dda7465a…(含 PR #667 的修复)