Skip to content

fix(live-voice): keep the microphone policy out of unrelated permissions - #1280

Merged
vastsa merged 1 commit into
vastsa:mainfrom
mingkun968:fix/live-voice-permission-scope
Oct 1, 2026
Merged

vastsa merged 1 commit into
vastsa:mainfrom
mingkun968:fix/live-voice-permission-scope

Conversation

@mingkun968

Copy link
Copy Markdown
Contributor

问题

应用自带的复制按钮全部失效:消息复制、表格复制、会话 ID 复制等都只给出「复制失败」,控制台报

NotAllowedError: Failed to execute 'writeText' on 'Clipboard': Write permission denied.

根因

installLiveMicrophonePermissionHandlers(apps/desktop/electron/main/index.ts)被装到了
session.defaultSession 上,而主界面 renderer 用的正是这个会话。

给会话安装 setPermissionRequestHandler / setPermissionCheckHandler 会覆盖该会话上所有权限的
默认决定
,而策略本身只按 media 判断:

if (input.permission !== "media" || !input.ownerValid || !input.leaseActive) return false;

于是 clipboard-sanitized-write 一并被拒,渲染层里全部 navigator.clipboard.writeText() 失败
(Markdown.tsx、MarkdownTable.tsx、Sidebar.tsx、TranscriptMenu.tsx、PluginInstallDialog.tsx、
ProviderHeadersEditor.tsx、OAuthLoginDialog.tsx、StartupRecovery.tsx、use-preview-target.ts)。
失败表现为「复制按钮坏了」,掩盖了真正的原因。

影响范围:v0.16.0-beta.1 与当前 main 均受影响;v0.15.10 正式版没有这个文件(复制正常)。

改动

  • microphone-permissions.ts:两个处理器只接管 media,其余权限保持平台默认;麦克风仍要求可信主
    frame + 有效租约,判定逻辑本身未改。
  • live-voice-permission.test.mjs:补上 clipboard-sanitized-write 的回归断言(原先断言
    notifications 为 false 的用例改为 true,即"非 media 权限不被本策略覆盖")。

验证

  • node --test apps/desktop/test/live-voice-permission.test.mjs:改前 AssertionError 失败 →
    改后通过
    (先把原文件放回去跑出红,再恢复修复跑出绿)。
  • 真实应用内复现:以隔离 profile 启动应用并接 CDP,在应用自己的渲染层里执行
    navigator.clipboard.writeText()(document.hasFocus() === true)→ 改前 Write permission denied,
    改后写入成功。
  • 本机未构建工作区包,完整 desktop 套件与 tsc 的结果与未改动的基线逐项相同
    (tests 2134 / pass 1921 / fail 208;tsc 1209 行),故无回归;完整 pnpm test 由 CI 执行。
  • pnpm check:agent-policy、pnpm check:pr-base 通过。

复现(修复前)

打开应用,点聊天内容里的复制按钮(或表格上的复制),或在渲染层直接执行:

navigator.clipboard.writeText("x").catch((e) => console.log(e.name, e.message));
// → NotAllowedError: ... Write permission denied.

installLiveMicrophonePermissionHandlers runs on session.defaultSession, which
also carries the main renderer. Installing a permission handler replaces the
platform default for every permission on that session, so limiting the policy
to `media` was never what actually happened: everything else was denied too.

clipboard-sanitized-write was denied with them, which made every
navigator.clipboard.writeText in the UI reject with "Write permission denied" —
the transcript copy button, the table copy button and the session id copy all
failed silently, and the failure looked like a clipboard problem rather than a
permission-scope one.

Non-media permissions now keep the platform default; `media` stays gated to the
trusted main frame with an active microphone lease. The Live Voice permission
test asserts the clipboard permission so the shadowing cannot come back.
@vastsa
vastsa merged commit 35d5d5d into vastsa:main Oct 1, 2026
4 checks passed

This branch was previously deployed

1 inactive deployment
Preview — 881a4b1e Deployed Oct 1, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants