Replies: 2 comments
|
逐项在 master(49a606bc5 = alpha.5 线)核实完毕——你的报告每个锚点都准确,机制链完整,是我见过最扎实的 locale 类 bug 报告之一。补充一个让修复更简单的结构事实,然后对三个方案给出裁决。 验证结果(全部命中)
补充结构事实:bash-sandbox 是 bash-local 的子类 → 单点修复成立
// bash-local/src/index.ts:198
env: { ...ENV_OVERRIDES, ...spec.env, ...spec.dshEnv }所以你的方案 1 具体化为在
副作用评估: 方案裁决
测试 locale 脆弱性——你的判断正确,补一个具体做法spec:519 通过与否确实随宿主 locale 漂移:上游英文 CI 永远绿,zh_CN 开发机永远红——这正是"平台盲区单靠 CI 抓不到"的典型。修复落地后该用例两种 locale 都绿,但在那之前(以及为了防止未来别的用例引入 locale 敏感文本),建议给该 spec 的子进程 env 显式钉 边界补充
|
|
补丁完成(含单测,已在当前 master 验证:原生 zh_CN 下 A/B——去掉 补丁(diff 基于当前 master): diff --git a/packages/shell/bash-local/src/index.ts b/packages/shell/bash-local/src/index.ts
index 064f124a00..833050e2fd 100644
--- a/packages/shell/bash-local/src/index.ts
+++ b/packages/shell/bash-local/src/index.ts
@@ -18,13 +18,20 @@ import type {} from '@deepseek-ai/dsh-settings'
import { clampTimeout, deadline, MAX_TIMER_DELAY_MS, timeoutOf } from '@deepseek-ai/dsh-timeout'
/**
- * Model-friendly environment overrides: disable colors, pagers, and
- * interactive terminal features that would garble tool output (the same set
- * Codex hardcodes; Claude Code achieves it via TERM=dumb). Bash-tool policy —
- * merged first into the spawn's explicit env, so a trusted caller's own entry
- * still wins; the subprocess service applies its credential scrub independently.
+ * Model-friendly environment overrides: disable colors, pagers, message
+ * localization, and interactive terminal features that would garble tool
+ * output or its diagnostics (the same set Codex hardcodes; Claude Code
+ * achieves it via TERM=dumb). `LC_ALL` takes glibc's top precedence (above
+ * `LANGUAGE`/`LANG`), so GNU tool error text stays the canonical English that
+ * the sandbox's denial classifier matches (`DENIAL_SIGNATURES` in sandbox-local
+ * are English substrings of the shell's stderr) instead of a host-locale
+ * translation that would silently under-report a denial as an ordinary
+ * failure. Bash-tool policy — merged first into the spawn's explicit env, so a
+ * trusted caller's own entry still wins; the subprocess service applies its
+ * credential scrub independently.
*/
export const ENV_OVERRIDES = {
+ LC_ALL: 'C',
NO_COLOR: '1',
TERM: 'dumb',
PAGER: 'cat',
diff --git a/packages/shell/bash-local/tests/executor.spec.ts b/packages/shell/bash-local/tests/executor.spec.ts
index 0f5b7992f3..89389e1ed6 100644
--- a/packages/shell/bash-local/tests/executor.spec.ts
+++ b/packages/shell/bash-local/tests/executor.spec.ts
@@ -160,6 +160,27 @@ describe('LocalBashExecutor.run', () => {
expect('env' in spec).toBe(false)
expect('dshEnv' in spec).toBe(false)
})
+
+ it('forces the child message locale to C even under a caller-supplied non-English locale', async () => {
+ // Hosts that default to a non-English system locale (UOS / Deepin in
+ // zh_CN, for one) make GNU tools report localized errors like `权限不够`
+ // / `只读文件系统`. The bash sandbox's denial classifier matches canonical
+ // English substrings of that stderr (`DENIAL_SIGNATURES`), so a localized
+ // message would silently under-report a sandbox denial as an ordinary
+ // failure. `LC_ALL` takes glibc's top precedence, so the fixed override
+ // keeps diagnostics English even when a caller or the parent still carries
+ // `LANG`/`LANGUAGE` — which stay forwarded for every non-message category.
+ // This pins that mechanism on any host, without needing a translated
+ // toolchain: the child's own view of its environment must show LC_ALL=C
+ // enforced while the caller-supplied LANG/LANGUAGE survive.
+ const { bash } = await setup()
+ const result = await bash.run(bash.resolve({
+ command: 'printf "%s|%s|%s" "$LC_ALL" "$LANG" "$LANGUAGE"',
+ env: { LANG: 'zh_CN.UTF-8', LANGUAGE: 'zh_CN' },
+ }))
+ expect(result.exitCode).toBe(0)
+ expect(result.stdout.text).toBe('C|zh_CN.UTF-8|zh_CN')
+ })
})
describe('LocalBashExecutor.start (background process handles)', () => {
|
Uh oh!
There was an error while loading. Please reload this page.
环境
0.1.2-alpha.4(masterHEAD4e84901)Linux 4.19.0-amd64-desktop,glibc 2.28)LANG=zh_CN.UTF-8、LANGUAGE=zh_CN(UOS/Deepin 桌面默认)一句话
bash-sandbox判定一次失败是否为「沙箱拒绝」(stampsandbox.denied)时,靠的是在 stderr 里大小写不敏感地匹配英文子串(如read-only file system、permission denied)。但 GNU bash/coreutils 的报错文本会按LC_MESSAGES/LANGUAGE本地化:在 zh_CN 下 bash 输出的是只读文件系统/权限不够,英文 signature 一个都匹配不上 →denied恒为false。中文 UOS/Deepin 桌面(以及所有非英文 locale 桌面)必现,而上游英文 CI 永远测不到。复现
A. 仓库自带单测,同一环境 A/B
packages/shell/bash-sandbox/tests/sandbox.spec.ts:519用例reports a real permission failure as a sandbox denial with the mode it ran under(写一个chmod 0555目录内文件,期望sandbox: { mode:'read-only', denied:true, enforcement:'full' })。B. 真实 bwrap runner(本机实际后端)zh vs C
对分类器(签名
['read-only file system','permission denied'])求值:bash: .../f: 只读文件系统bash: .../f: Read-only file systembash: .../f: 权限不够bash: .../f: Permission denied根因链(源码级)
scrubbedParentEnv()(packages/subprocess/subprocess/src/index.ts:60),它刻意保留 locale 变量(同文件:49注释:"PATH, HOME, locale, and proxy variables survive")。packages/shell/bash-local/src/index.ts:27ENV_OVERRIDES)只有NO_COLOR/TERM=dumb/PAGER=cat/GIT_PAGER=cat,没有任何LC_*;bash-sandbox的 confined 路径复用同一spawnSpec。zh_CN.UTF-8,写失败时由 gettext 输出本地化诊断(只读文件系统/权限不够)。DENIAL_SIGNATURES(packages/sandbox/sandbox-local/src/index.ts:205附近):bwrap: ['read-only file system']、landlock: ['permission denied']、runnerCommand: ['read-only file system','permission denied']—— 全英文子串。classifyDenial→matchesSignature(packages/shell/bash-sandbox/src/helpers.ts:67,112)做大小写不敏感的子串匹配。本地化文本不含英文子串 →denied:false。影响
sandbox.denied这一结构化信号静默丢失:run 返回非零退出,但 harness 认为是「普通命令失败」而非「策略拒绝」。denied的行为全部失效:拒绝提示与引导 UI、基于策略的转述、denial 统计等。附带问题:该单测套件本身 locale 脆弱
该用例通过与否取决于宿主 locale —— 上游 CI(英文)永远绿,zh_CN 开发机(任何 UOS/Deepin 贡献者)会红。这类平台盲区正好是单靠 CI 抓不到的,建议无论采用哪种修复,都让「工具产物/测试」在确定 locale 下运行。
候选修复(供维护者定夺)
bash-local的ENV_OVERRIDES或bash-sandbox的 confine env 里加LC_ALL: 'C'(注意LANGUAGE优先级高于LC_MESSAGES,需一并置空或设LC_ALL压制之;glibc 下LC_ALL优先于LANGUAGE)。这与现有「model-friendly environment」覆盖(禁色/禁分页)的意图一致——工具输出本就该可确定解析。代价:子进程整体输出走 C locale(日期/排序等变规范,对 agent 消费反而更可预期)。备注
pwsh-sandbox(packages/shell/pwsh-sandbox/src/index.ts:121,167)走同一条classifyDenial/matchesSignature,若 PowerShell 在目标 locale 下也本地化报错文本则同样受影响;本机未装 pwsh 未实测,供维护者留意。All reactions