MoonshotAI / MoonshotAI/kimi-code
Approval prompt never renders in web/desktop/VS Code clients when a PreToolUse or SessionHeartbeat hook is configured — pending call is then silently approved
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 7.5k
- Forks
- 1.2k
- Avg merge
- 11h 53m
- Merged PRs (30d)
- 350
Description
Environment
- OS: macOS (arm64)
- Kimi Code CLI: 0.43.1, reproduced again after upgrading to 2.0.0
- Clients affected:
kimi webofficial web UI, Kimi Code desktop app 1.0.1, VS Code extension 0.7.5 - Terminal TUI: not affected (approval prompts render and wait for input normally)
Summary
When a hook is configured on PreToolUse (or SessionHeartbeat), approval requests never render in server-driven clients (web UI, desktop app, VS Code extension). The desktop app shows an "Internal error occurred." toast instead. Worse: the pending approval is later resolved as approved with zero user interaction, and the tool call — including destructive commands such as rm — executes unattended. In manual (Always Ask) permission mode this silently disables the human approval gate.
Steps to reproduce
-
Add to
~/.kimi-code/config.toml:[[hooks]] event = "PreToolUse" command = "/bin/true"The hook binary itself is irrelevant; any hook that exits 0 quickly reproduces the issue.
-
Open a session in the web UI (
kimi web), permission mode: Always Ask (manual). -
Have the agent run a command that requires approval, e.g. create a temp file with
touch /tmp/probe.txt, then delete it withrm /tmp/probe.txt. -
Observe: no approval card appears; the command executes regardless.
Expected behavior
- Approval prompts render in every client regardless of hook configuration.
- If approval delivery or rendering fails for any reason, the decision must fail closed (deny the call or surface an error). It must never resolve as
approvedon its own.
Actual behavior
-
No approval UI in web/desktop/VS Code clients; desktop app shows an "Internal error occurred." toast.
-
The session wire log shows the approval resolved without any client/user action in between:
{"type":"interaction.request","kind":"approval","toolName":"Bash","action":"Running: rm /tmp/probe.txt"} {"type":"interaction.resolved","response":{"decision":"approved"}} {"type":"permission.record_approval_result","toolName":"Bash","action":"Running: rm /tmp/probe.txt","result":{"decision":"approved"}} -
The tool executes.
Bisect
Same session, one variable at a time; does the approval card render?
| Hook configuration | Approval card |
|---|---|
| (no hooks) | yes |
PermissionRequest only |
yes |
PermissionRequest + PreToolUse |
no |
PermissionRequest + SessionHeartbeat |
no |
SessionStart + SessionEnd + PermissionRequest + Stop + StopFailure + Interrupt |
yes |
Pattern: hooks that fire before or while an approval is pending break the approval UI; events firing at or after the approval are harmless. UserPromptSubmit was not tested in isolation but falls into the "fires before the approval" group. Results identical on CLI 0.43.1 and 2.0.0.
Impact
Security-relevant. In manual mode the user expects every sensitive operation to wait for an explicit decision. With such hooks configured — a documented, supported feature — that guarantee silently disappears: approvals resolve themselves and commands run unattended. Not remotely exploitable (requires a local hook configuration), but the failure mode must be fail-closed, not fail-open.
Notes
- The hook in our real setup exits 0, writes nothing to stdout, and completes in under a second; it complies with the documented hook contract.
- Desktop app log, VS Code extension bridge log (
respondApprovalentries with no corresponding user action), and session wire logs available on request.
中文版本 (Chinese version)
环境
- 系统:macOS(arm64)
- Kimi Code CLI:0.43.1;升级到 2.0.0 后问题依旧
- 受影响客户端:
kimi web官方网页版、Kimi Code 桌面应用 1.0.1、VS Code 扩展 0.7.5 - 终端 TUI:不受影响(审批提示正常渲染并等待用户输入)
问题概述
当配置了 PreToolUse(或 SessionHeartbeat)事件的 hook 后,服务端驱动的客户端(网页版、桌面应用、VS Code 扩展)不再渲染审批请求;桌面应用弹出 "Internal error occurred." 提示。更为严重的是:处于等待状态的审批随后在无任何用户操作的情况下被以 approved 解决,相关工具调用——包括 rm 等破坏性命令——在无人值守下直接执行。在"始终询问"(manual)权限模式下,这等于人工审批机制被静默失效。
复现步骤
-
在
~/.kimi-code/config.toml中添加:[[hooks]] event = "PreToolUse" command = "/bin/true"hook 程序本身与故障无关,任何快速以 0 退出的程序均可复现。
-
在网页版(
kimi web)中打开会话,权限模式设为"始终询问"(manual)。 -
让 Agent 执行一条需要审批的命令,例如先
touch /tmp/probe.txt,再rm /tmp/probe.txt。 -
观察现象:审批卡片不出现,命令仍然被执行。
预期行为
- 无论是否配置 hook,审批提示都应在所有客户端正常渲染。
- 审批的下发或渲染无论因何种原因失败,结果必须 fail-closed(拒绝调用或显式报错),绝不应在无人决策的情况下自动变为
approved。
实际行为
-
网页版 / 桌面应用 / VS Code 扩展均不显示审批界面;桌面应用提示 "Internal error occurred."。
-
会话 wire 日志显示审批在没有任何客户端/用户操作的情况下被解决:
{"type":"interaction.request","kind":"approval","toolName":"Bash","action":"Running: rm /tmp/probe.txt"} {"type":"interaction.resolved","response":{"decision":"approved"}} {"type":"permission.record_approval_result","toolName":"Bash","action":"Running: rm /tmp/probe.txt","result":{"decision":"approved"}} -
工具调用照常执行。
二分定位
同一会话、每次只改一个变量,观察审批卡片是否渲染:
| hook 配置 | 审批卡片 |
|---|---|
| (无 hook) | 正常 |
仅 PermissionRequest |
正常 |
PermissionRequest + PreToolUse |
不渲染 |
PermissionRequest + SessionHeartbeat |
不渲染 |
SessionStart + SessionEnd + PermissionRequest + Stop + StopFailure + Interrupt |
正常 |
规律:在审批产生之前或审批等待期间触发的 hook 会导致审批界面崩溃;在审批之时或之后触发的事件无影响。UserPromptSubmit 未单独隔离测试,但同属"审批前触发"一类。CLI 0.43.1 与 2.0.0 上现象一致。
影响
属于安全相关缺陷。manual 模式下用户预期所有敏感操作都必须等待明确授权;而配置了上述 hook——这是官方文档支持的功能——之后,该保证被静默破坏:审批自行通过,命令无人值守执行。该问题不可远程利用(前提是本地存在相应 hook 配置),但其失败模式必须是 fail-closed,而非 fail-open。
补充说明
- 我们实际使用的 hook 程序退出码为 0、stdout 无任何输出、执行耗时不足 1 秒,完全符合文档约定的 hook 行为规范。
- 桌面应用日志、VS Code 扩展 bridge 日志(存在无用户操作对应的
respondApproval调用记录)及会话 wire 日志均可提供。
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Reproduce with the documented PreToolUse or SessionHeartbeat hook in ~/.kimi-code/config.toml, then compare the web UI, desktop app, VS Code extension, and unaffected terminal TUI while capturing the session wire log. Trace interaction.request through interaction.resolved and permission.record_approval_result; done means approval renders in affected clients and any delivery or rendering failure denies or surfaces an error rather than approving.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript, vscode
- Domain
- authorization, frontend, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100