ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Apache Maka 代码库 Bug/流程审计实录:13 项权限边界与运行态一致性修复深度解读

Apache Maka 代码库 Bug/流程审计实录:13 项权限边界与运行态一致性修复深度解读 Apache Maka 代码库 Bug/流程审计实录13 项权限边界与运行态一致性修复深度解读【免费下载链接】makaApache Maka (Incubating) is a high-performance agent workspace that keeps a complete record of everything it did.项目地址: https://gitcode.com/GitHub_Trending/mak/maka本文基于 Apache MakaIncubating仓库中的一份时间点审计文档《Maka Code Bug / Flow Audit - 2026-05-22》后于 2026-07-13 归档属于历史快照而非当前实现指南展开。审计覆盖 runtime / main / renderer / core / storage / settings 六个代码面围绕权限边界、会话状态机、流式 UI 一致性、提示词组装、健康探测五类问题展开。读完本文你将理解Maka 如何封堵 shell 命令静态分类的逃逸、如何把读/写工具约束在会话 cwd 之内、如何在后端构建失败时保持会话状态一致、以及 skills 与工作区指令AGENTS.md 等如何被安全注入系统提示词——每个结论都有仓库源码与回归测试佐证。一、审计背景与范围该审计是一次快照式排查以 2026-05-22 的代码状态为准Owner 为 xuanLayout 相关工作由 yuejing 另行跟踪。审计产出分三部分已修复问题13 项每项都带有修复 commit、问题证据、影响评估、修复方案与回归测试位置遗留产品/架构发现A–D 共 4 项属于产品决策或后续工程任务不阻塞当前修复验证日志修复后的完整测试计数。截至审计时点已推送的修复 commit 依次为778077d、a4a9b7e、21522a9、1e41f64、5c324c4、0afcf2e后续修复health probe、write-tool containment、session-id containment尚未单独记录 commit 号。二、已修复问题权限边界与路径逃逸这类问题共 5 项全部指向同一个核心矛盾工具契约承诺会话工作区内工作但实现允许越过该边界。1. Shell safe-prefix 命令绕过 Ask 弹窗修复 commit778077d证据与影响packages/core/src/permission.ts在检查通用 shell 控制操作符之前先对安全前缀命令做了分类导致echo hello out.txt、cat package.json | wc -l、pwd npm test、反引号、$()等形态可能被归类为shell_safe。Ask/Explore 模式下这些命令会自动放行而它们实际可能改写文件、串联命令甚至展开含密钥的命令替换。修复新增SHELL_CONTROL_PATTERNS在安全前缀匹配之前先把这类命令归类为shell_unsafe回归测试落在 packages/core/src/tests/permission.test.ts。源码层面的深化当前 permission.ts 的注释已经明示了这一修复的最终形态——根本不存在 SAFE_SHELL_PREFIXES 白名单静态字符串无法证明 shell 命令安全$(...)、反引号、iex都会先执行甚至git status也可能触发 fsmonitor 辅助进程。因此categorizeBash()永远不会返回shell_safe该分类在ToolCategory中标注为reserved / fail-closed见 L72只读诉求必须走Read/Glob/Grep这类固定 argv、无 shell的类型化工具而每一条 shell 命令至少落入shell_unsafe → 弹窗确认。分类函数categorizeBash的职责退化为给出更准确的确认理由通过commandSegments()按|;\n(){}切分每条语句段经normalizeSegmentHead()去掉引号/转义/路径前缀/包装命令nohup、timeout、env 等后按privileged fs_destructive git_destructive shell_unsafe的优先级选择确认理由。注释中特别强调错过一个变体只是措辞瑕疵而非绕过——因为兜底本身就是弹窗。8. 自动放行的只读工具可逃逸会话 cwd修复 commit21522a9证据与影响Read、Glob、Grep被标记为permissionRequired: false但接受绝对路径、../或符号链接逃逸意味着 Explore/Ask 模式能在不弹窗的情况下读取会话工作区之外的文件。修复Read拒绝绝对路径并以词法 realpath 双重包含检查约束在会话 cwd 内Glob拒绝绝对路径/父级穿越模式并约束可选 cwdGrep约束可选路径在会话 cwd 之下。回归测试落在 packages/runtime/src/tests/builtin-tools.test.ts。包含检查的底层实现在 packages/runtime/src/path-containment.ts 的isPathInside(root, target)该函数同时被 managed skill-source 存储、filesystem worker、workspace executor 复用是路径边界的公共原语。12. Write/Edit 写类工具可逃逸会话 cwd当前 write-tool containment 变更集证据与影响Read/Glob/Grep已被约束后Write与Edit仍只做resolve(cwd, path)。绝对路径与../穿越在权限模式允许工具时能写向会话 cwd 之外符号链接父目录也能把一次写入引到工作区外。尤其 Execute 模式下Write/Edit依策略放行因此需要硬性路径边界。修复Write在写入前拒绝绝对路径、父级穿越与符号链接父目录逃逸Edit复用 realpath 包含检查辅助函数拒绝绝对路径、父级穿越与符号链接文件逃逸两者均补充回归测试。13. 会话存储接受路径形状的 session id当前 session-id containment 变更集证据与影响FileSessionStore.sessionDir(sessionId)直接把 renderer/runtime 提供的 id 拼到workspaceRoot/sessions之下remove(sessionId)等操作在路径校验存在前可能收到穿越形状的 id。虽然常规调用都是 UUID但 IPC/runtime 边界仍应在任何文件系统操作前拒绝路径形状的 id。修复会话存储只接受匹配[A-Za-z0-9_-]{1,128}的有界 idlist()跳过畸形目录所有文件系统路径与写队列在读、写、删前断言同一 id 契约。回归测试验证了穿越 id 会被拒绝且不会删除外部的受害者目录。这一 id 形状约束在仓库中同样出现在其他身份校验处如 session-projection-helpers.ts 对 WorkHub direct-stop action id 的^[A-Za-z0-9_-]{1,128}$断言可见先验证身份、再触碰文件系统已成为统一惯例。三、已修复问题会话状态机与流式 UI 一致性这类问题共 4 项核心是后端异步失败/中止时持久化状态与界面状态必须同步收敛。2. 用户追加后后端构建/发送失败留下假会话状态commit778077d证据与影响packages/runtime/src/session-manager.ts 在后端创建之前就追加了用户消息与运行中turn 状态而后端构建失败发生在活动流簿记/finally 状态迁移之前导致持久化的用户消息可能停留在 running/active而不是 failed/blocked。修复把连接锁、后端构建、流簿记、后端发送整体包进单个 try/finallycatch 中追加失败 turn 状态最终 header 变为blocked/unknown回归测试落在 packages/runtime/src/tests/session-manager.test.ts。从源码看SessionManager正是把三件事绑定在一起的公共 Runtime APISessionStore来自maka/storage的 SQLite 持久化、AgentBackend如AiSdkBackend、ExecutionBoundary会话沙箱权威这次修复补上的正是三者交界处最容易被忽略的失败路径。3. Renderer 过期消息刷新可能覆盖当前会话commit778077d证据与影响apps/desktop/src/renderer/main.tsx的refreshMessages(sessionId)无条件执行setMessages(await readMessages(sessionId))若异步读取在途期间用户切换会话旧会话数据会覆盖当前聊天视图。修复用activeIdRef.current sessionId守卫setMessages保证只有当前活跃会话的读取结果才能落地到视图。4. 出错/中止/完成后流式与权限 UI 可能卡死commit778077d证据与影响错误与中止事件会刷新会话/消息但并未一致地清理流式文本或挂起的权限弹窗状态导致 turn 已失败/中止后 composer/会话 UI 仍停留在 streaming/waiting。修复新增clearStreaming(sessionId)在 error/abort 时同时清理流式文本与挂起权限状态非权限型 complete 也会清理流式状态。7. Stop 未拒绝挂起的工具权限请求commita4a9b7e证据与影响AiSdkBackend.stop()中止了模型流但没有结束当前 permission-engine turn若某个工具正等待权限弹窗Stop 可能让工具包装一直停放到用户稍后做出决定。修复stop()现在调用permissionEngine.endTurn(currentTurnId, aborted)回归测试落在 packages/runtime/src/tests/ai-sdk-backend.test.ts。源码层面的深化在 ai-sdk-backend.ts 中可以看到stop()的注释进一步说明了 turn 语义的演化——每个 turn 现在都以自身的abort controller、自身的 ToolRuntime、自身的 turn id 收尾早先共享同一个currentTurnId会导致并发 turn 在收尾时错误地挂到兄弟 turn 的身份下。注释还强调endTurn是唯一能让停在askUserQuestion上的工具解除的东西abort 信号不会唤醒注册表因此收尾必须对每个作用域都完成不能因首个失败而跳过其余兄弟。四、已修复问题提示词组装与技能注入这类问题共 3 项主题是UI 展示的能力与模型实际收到的指令必须一致。6. Skills 被列出但未注入运行时提示词commita4a9b7e证据与影响skills:list会扫描{workspaceRoot}/skills/*/SKILL.md但buildSystemPrompt()只包含个性化内容模型从未收到技能指令——UI 让技能看起来已安装实际是空转。修复把技能扫描与提示词组装抽取到apps/desktop/src/main/skills.tsbuildSystemPrompt()现在包含有界的本地技能指令提示词片段明确声明技能优先级更低、不能授予工具、不能绕过权限、不能覆盖更高优先级指令。测试落在apps/desktop/src/main/__tests__/skills.test.ts。运行时侧对应的技能发现与状态管理在 packages/runtime/src/skills-discovery.ts 与 packages/runtime/src/skills-state.ts。10. 提示词组装缺乏工作区指令上下文commit0afcf2e证据与影响buildSystemPrompt()已含个性化与已安装技能但未读取活动会话 cwd 下的项目本地工程指令编码会话可能忽略仓库本地规则如AGENTS.md除非用户手动重复。修复运行时系统提示词回调现在接收{ sessionId, cwd, workspaceRoot }桌面端提示词组装从会话 cwd 读取有界白名单文件AGENTS.md、CLAUDE.md、GEMINI.md加载器做 realpath 包含检查、跳过符号链接逃逸、剔除控制字符、限制单文件与总提示词大小并把这些工作区文件标记为低优先级/不可信上下文——不能授予工具、不能削弱权限。源码层面的深化该逻辑现已收敛到 packages/runtime/src/system-prompt/workspace-instructions.ts并被 CLI/TUI 与桌面端共用注释说明它从apps/desktop/src/main/workspace-instructions.ts迁入避免重复读路径。关键常量WORKSPACE_INSTRUCTION_FILES [AGENTS.md, CLAUDE.md, GEMINI.md]单文件上限MAX_WORKSPACE_INSTRUCTION_FILE_CHARS 6000、提示词总量上限MAX_WORKSPACE_INSTRUCTIONS_PROMPT_CHARS 14000见 L42-L43。加载顺序为用户全局~/.maka/同名文件global scope→ 会话 cwd 项目文件project scope渲染为workspace-instructions file... scope...片段并显式声明不可信、优先级低于系统/开发者/安全/权限规则。两个值得注意的实现细节一是用清洗后文本的 sha256 摘要去重——同一目录下通过符号链接或复制让多份文件同名是不同 CLI 生态的惯用法realpath 无法识别复制形式的重复二是文件内容在截断前先摘要即仅在容量上限之后分叉的两份文件仍是不同指令。对应测试在 packages/runtime/src/tests/workspace-instructions.test.ts。9. 主进程流 catch 发射随机 turn idcommit1e41f64证据与影响streamEvents()的 catch 用turnId: randomUUID()合成 renderer 错误事件即使 runtime 已持久化正确的失败 turnrenderer 错误事件也可能脱离真实 turn 血缘。修复send/retry/regenerate/quick-chat 现在生成显式 turn id 并作为fallbackTurnId传入streamEvents()catch 使用该 id 同时发射会话与 turn 状态变更事件。五、已修复问题就绪契约与健康可观测性5. 打包应用可从 renderer 输入创建 FakeBackend 会话commit778077d证据与影响apps/desktop/src/main/main.ts直接接受 renderer 的sessions:create({ backend: fake })打包应用因此存在一条绕过真实就绪契约的假会话创建路径。修复新增canCreateFakeSessionFromRenderer()仅允许在未打包的开发/视觉冒烟环境下创建假会话。11. Health Center 有校验信号但缺 LLM 运行时探测信号当前 health-probe 变更集证据与影响health:getSnapshot只发射healthSignalFromConnection()LLM 行仅代表连接测试校验lastTestStatus而非真实的 send/stream/abort 路径。UI 正确表达了verified ! operational但没有首个运行时信号来展示某连接是否真实发送成功、失败或被中止。修复LLM 遥测记录新增connectionSlugTelemetryRepo可返回每个连接/模型的最新运行时探测Health 快照为每个已启用连接发射独立的runtime_probe信号首次发送前 unknown、最近一次成功后 ok、用户中止后 info、最近一次运行时错误后 warning。健康/能力中心的对应实现位于 apps/desktop/src/main/capability-snapshot.ts其buildPermissionSnapshot()已能把 macOS 的 TCC 权限accessibility / screen_recording / automation 等映射为结构化快照为UI 不再对运行状态撒谎提供了基础设施。六、遗留产品与架构发现A–D这四项属于审计时尚未解决的产品/架构问题文档给出了明确的风险与建议方向A. Coming Soon 设置项仍需产品决策SettingsModal.tsx 把daily-review、voice-models、open-gateway、search暴露为启用的导航项并配 Coming Soon 文案packages/core/src/settings.ts 已有 section id但这些功能尚无真实 settings 契约。建议由 WAWQAQ 逐页决策现在实现、从导航隐藏、或保留为禁用路线图文案若保留可见每个页面需先有真实的 snapshot/status 来源。B. Health/Capability 中心仍只有部分探测完成capability-snapshot.ts将 Computer Use、Activity、Voice、Open Gateway、Memory Write 标记为not_available带脚手架原因。Bot readiness 已更安全、LLM 连接健康已有首个真实运行时信号但多数非 LLM 运行时探测仍是占位符。建议在翻转任何非 LLM 行为 enabled/operational 之前先实现真实探测Computer Use 需要真实 helper 进程 AX/截图探测Voice 需要麦克风/TTS 块探测Open Gateway 需要心跳。C. 主/渲染/设置/UI 组件文件仍然过大审计时main.ts1300 行、main.tsx1428 行、SettingsModal.tsx1643 行、packages/ui/src/components.tsx 2654 行、ai-sdk-backend.ts 912 行。风险是修复难以隔离、合并冲突增加、事件/状态耦合易漏。建议按职责归属拆分而非任意提取 helpermain IPC 按 sessions/connections/settings/artifacts/capabilities/skills 分模块renderer 按 session 事件 reducer / settings shell / chat shell 拆分ui components 按 chat/sessions/permissions/composer/tool activity 拆分runtime backend 按 stream pump / tool wrapper / telemetry-artifact hooks 拆分。D. Open Gateway / search / voice / daily review 仍是 no-op 路线图功能只有 Coming Soon UI 文案与 capability snapshot 占位符无后端实现。风险是用户可能把导航误读为功能已存在。建议在每项具备 snapshot/degraded/revoke/audit/probe 契约之前不接线按钮/开关全部保持禁用文案或直接隐藏。七、验证日志与工程启示修复后的验证过程本身也值得记录来源审计文档的 Verification Log最新修复后git diff --check通过、npm run typecheck通过0afcf2e之后全量npm test --workspaces --if-present通过core 122 / storage 38 / runtime 99 / desktop 327 586runtime health probe 工作之后再次全量通过core 124 / storage 39 / runtime 99 / desktop 327 589。从这批修复可以提炼出 Maka 在安全与状态一致性上反复出现的四条工程原则不可证明安全即不安全shell 命令的运行时效果在静态字符串上不可判定因此不设安全前缀白名单改用类型化只读工具 全部 shell 弹窗 精确确认理由的 fail-closed 模型见 permission.ts 顶部注释。路径边界必须落在每次文件系统操作之前无论是工具参数Read/Glob/Grep/Write/Edit还是会话 idFileSessionStore统一先做有界校验词法 realpath 包含、[A-Za-z0-9_-]{1,128}共享isPathInside()原语。失败路径与成功路径同权后端构建失败、流错误、用户 Stop 都必须把持久化 turn 状态、renderer 流式状态、权限弹窗状态三处同时收敛否则 UI 会看起来还在运行。展示能力必须有真实证据技能要进提示词、工作区指令要按白名单与大小上限注入、健康中心要有真实 send/stream/abort 运行时信号在真实探测实现之前宁可标not_available也不把占位符当能力展示。需要说明的是本文所依据的审计是 2026-05-22 的时间点快照其中部分文件如permission.ts、workspace-instructions.ts、ai-sdk-backend.ts在后继迭代中持续演化文中的源码引用以当前仓库实际内容为准仅用于印证审计描述的修复方向与底层机制。【免费下载链接】makaApache Maka (Incubating) is a high-performance agent workspace that keeps a complete record of everything it did.项目地址: https://gitcode.com/GitHub_Trending/mak/maka创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表