Repository navigation
fix(shells): declare meta tool names and refuse a host-binary argv - #565
tietoumiao wants to merge 1 commit into
Conversation
Declare the progressive-disclosure, PTC batch and PTC SDK loader tools in their own x-tool-namespaces entry so the manifest advertises the surface the plugin publishes, and assert that every x-components name reaches a namespace. Refuse a confined argv whose head is the host Electron binary: without ELECTRON_RUN_AS_NODE it opens a second GUI instance that exits 0 without running the command, which was indistinguishable from success. Report EXECUTOR_UNAVAILABLE instead of a silent pass.
Haoming9527
left a comment
There was a problem hiding this comment.
Reviewed 519ea68 against the already prepared #543 and #572. The missing manifest inventory and silent Electron startup are valid problems; there are two concrete gaps in this alternative guard.
- [P2] Normalize the Windows executable path before comparing it (
src/shells/host-runner.ts,argv[0] !== host.execPath). Case and slash variants identify the same executable on Windows. The guard returnsundefinedfor an uppercase/forward-slash spelling ofprocess.execPath; I also launched a harmless Node probe through that spelling and confirmed it resolves to the same image. An equivalent host runner path can therefore evade the refusal. - [P2] Do not accept an ambiguous Node-mode environment (
nodeModeRequested). With{ ELECTRON_RUN_AS_NODE: '0', electron_run_as_node: '1' },.some()returns true, but an actual Windows child receivesELECTRON_RUN_AS_NODE=0. The guard therefore admits a runner whose effective environment does not request Node mode. Require one unambiguous effective setting and test case-colliding keys; POSIX matching should remain case-sensitive.
These controls were run against the exact helper from this PR. The comparison through #543's execution boundary rejected both inputs with zero spawns. No live Electron GUI was used, so this evidence establishes the guard behavior and Windows path/environment semantics, not Desktop runtime recovery.
Please coordinate with #543 for the runner guard and #572 for the manifest inventory. #572 validates exact coverage of the production capability catalogue and documents that inventory does not itself publish or authorize tools. Applying both versions would duplicate the namespace entries and overlap the runner logic. The integration path is #557; this PR remains open for author revision rather than being silently replaced. No CI approval or merge has been performed as part of this review.
Nicholas023
left a comment
There was a problem hiding this comment.
审查结论:REQUEST_CHANGES — 建议关闭(或只保留 components ⊆ namespaces 一条)
manifest 半边是对的,但 runner 守卫的两个谓词各有可复现缺陷。
1. Windows 路径比较未归一化,四类拼写全部绕过(阻断)
src/shells/host-runner.ts:48 是 argv[0] !== host.execPath 的字符串比较。用真实 process.execPath 逐变体注入:
text 变体 解析到同一映像 守卫拒绝 原样 是 是 全大写 是 否 正斜杠 是 否 8.3 短名 NICHOL~1 是 否 \\?\ 扩展前缀 是 否
fs.realpathSync.native 对这四类都判 sameImage=true,且 spawn 实测成功。注意 path.resolve + toLowerCase 只能修前两类,修不了 8.3 与 \\?\ —— 只有 realpath 比较能覆盖。
2. POSIX 上是真 fail-open(维护者这条的因果判断有误)
nodeModeRequested() 无条件 key.toUpperCase()。POSIX 环境名大小写敏感、Electron 的 getenv("ELECTRON_RUN_AS_NODE") 也大小写敏感,所以 {electron_run_as_node:"1"} 在 Linux/macOS 会被放行,而 Electron 根本看不到该变量 → 仍然开第二个 GUI 实例。
同时给出一个反证:Electron 源码 shell/common/process_util.cc 用 base::Environment::HasVar(kRunAsNode),electron_main_win.cc 用 getenv_s(...) != 0 —— 变量存在即生效,与值无关。所以 ELECTRON_RUN_AS_NODE=0 也会进 Node 模式,本 PR 的 value === '1' 是过严(fail-closed 误杀),不是放行。而 test/shells-host.test.mjs:370 恰好把 POSIX 上的错误行为钉死了。
3. manifest 部分与 #572 重复
两者都补 batch/load_sdk/discover_tools。朴素合并会产生 4 个 namespace、3 个工具各声明两次,而本 PR 自己新增的「declared by exactly one namespace」规则会把这种重复判红。
已核实为真的部分
manifest14/14、shells-host25/25、validate-manifest108/108- 两条 revert-red 都真红
- 0.5.0 基线确实缺三个 namespace 条目(
x-tool-namespaces仅 2 条目 / 17 工具)
处置建议
关闭。 唯一有价值的是 components ⊆ namespaces 校验规则,请单独 rebase 到 #572。
|
Closing — #572 landed the namespace inventory in |
Closes #484
What was wrong
Two defects in the declared shell surface:
dsh-plugin.json:140-142declared three tool names (batch,load_sdk,discover_tools) thatno
x-tool-namespacesentry at:68-104covered, so the manifest advertised a surface thevalidator's namespace rule could not reconcile.
src/shells/session-execution.ts:41passedconfinement.argvthrough unchanged. When the hosthands the Electron binary as the argv head, the plugin spawned a second GUI instance that
exits 0 without running a shell — a silent no-op the model cannot tell from success.
The change
dsh-plugin.json— the three meta tools get their ownx-tool-namespacesentry, so the declarednames and the declared namespaces agree.
src/shells/host-runner.ts(new, 50 lines) +src/shells/session-execution.ts— a confined argvwhose head is the host Electron binary is refused with
EXECUTOR_UNAVAILABLEand an actionablemessage instead of being spawned.
scripts/validate-manifest.mjs— the namespace rule plus acomponents ⊆ namespacescheck (theone file in the commit not literally named by the issue; without it
npm run verifyrejects thenew namespace entry).
test/manifest.test.mjs,test/shells-host.test.mjs,docs/CHANGELOG.md.Deliberately not done: no trampoline rewrite of the host's
windows-acl-runner.js(host-internal),and the
bashRefusalValuerendering half fixed by #520 is untouched.Validation
docs/CHANGELOG.md## [Unreleased]:已加(EN+ZH)pull_request事件触发,届时回填CI required的 run URLEnvironment
065cd7fnpm ci --ignore-scripts未验证 / 风险披露
HostRuntime+ 模拟process.versions.electron证明;"宿主是否真的把
[process.execPath, runner]交下来"取自 issue 的现场,未再次推导。scripts/validate-manifest.mjs的改动请重点看一眼:它把"声明必须自洽"变成可执行规则。check:size541→542 文件,均 ≤1000 行。CI