Skip to content

v2.17.0

Choose a tag to compare

@DearTang DearTang released this 14 Oct 11:50
· 22 commits to main since this release

MyShell v2.17.0 更新说明

本版本是一次针对 AI 接入安全边界的审计整改。审计推翻了我方上一轮的核心推测(前后端确认规则集可能存在偏差 → 并不存在),转而修复了三处真实问题:确认门依赖中文错误文案判定、不可逆文件操作的确认弹窗藏在窗口后面、以及保险库解锁缺少可轮询的等待契约。

🔒 安全

  • MCP 确认门不再依赖错误文案的措辞:ssh_exec 判定「可见确认框是否出现过」时,用 e.message.contains("未找到 myshell.exe") 一类字符串匹配来决定能否回落无头执行 —— 也就是确认门本身建立在错误措辞之上,改一个错字或加一个条件分支,都会让判定翻转,高危命令静默执行。现改为 enum GuiLaunchError + gui_reachable(),可达性作为类型信息随 GuiExecError 传递,文案只用于显示;并新增回归测试 gui_reachability_comes_from_type_not_wording 锁死该性质
  • 确认超时按「拒绝」处理:mcp_confirm 等待 180 秒无决策即判为拒绝。不可逆操作里「用户没说好」必须读作「不」——若读作「是」,则「一直等下去」反而变成无条件放行

✨ 新增

  • 不可逆文件操作的确认改在 MyShell 界面内渲染:sftp_upload / sftp_remove / sftp_rename / upload_project / download_project / zmodem_upload 六类操作此前由 MCP 进程弹 Windows 原生对话框 —— 用户在 MyShell 窗口里工作时那个框会藏在窗口后面并抢走焦点,而这六类恰恰不可逆(覆盖、删除),漏看一次框就等于漏掉一次确认,AI 则会一直等待。现复用命令确认的既有弹窗组件;并发第二个弹窗会被拒绝(避免顶掉第一个导致其回调丢失);GUI 完全不可用时才回退原生对话框
  • vault_status 只读工具:返回 gui_running / initialized / unlocked 三个布尔与 vault_state,不泄漏任何连接元数据(保险库锁定时 AI 仍看不到任何连接名、主机或凭据)

🛠️ 优化

  • 登录门禁给出可轮询的等待契约:此前保险库未解锁时,AI 拿到的只是一段中文提示,只能盲猜重试时机。现失败返回结构化的 error_kind: "vault_locked" 与 vault_state(locked / not_initialized / gui_unavailable / ipc_unresponsive)及明确指引。仍不做隐式等待——多数 MCP 客户端 30 秒左右就会放弃单个请求,隐式等待必然双重失败;改为由 AI 调 vault_status 每 5 秒轮询一次(约 2 分钟上限)后重试同一个工具。门禁状态由 enum VaultGateError::state() 导出,不再从中文文本匹配
  • 侧栏连接树左侧空白收敛:此前每行的左缩进由两处叠加 —— 行 margin-left: 6px 加上自身 padding-left,深度节点再叠加 depth * 14px。实测文件行图标前空 22px、连接行前空 30px(侧栏最窄 200px 时白白浪费约 1/10 宽度)。现改为单处承担:文件行 8px、连接行 12px,层级步进同时由 14px 收到 12px;搜索框左缘一并对齐。右侧保持不变(「⋯」贴右缘是上一版用户已确认的结论)
  • 新增 4 组安全回归测试:23 种命令绕过形态(do rm / timeout 30 rm / nohup rm / xargs rm / 'rm' / /bin/rm / ( rm ) / { rm; } / if…fi / 管道后半段 / 反引号 / $() / >& / chmod -R / mkfs / dd / shutdown / sudo …),任一回退为「不弹确认」即失败;另有只读命令不得误弹的反向闸门(确认噪音会训练用户闭眼点确认)、错误类型可达性映射、门禁状态可读性