Skip to content

security(qa): 净化 QA assistant markdown,避免 WebView XSS 读取凭据 #221

@appergb

Description

@appergb

背景

安全扫描发现 QA 浮窗会把 assistant / streaming answer 的 markdown 直接渲染到 Tauri WebView。这个 issue 只跟踪 QA markdown 渲染安全边界,不混入 CSP 重构、凭据存储迁移或 UI 调整之外的其他工作。

风险

当前链路里,assistant 内容经 marked.parse(...) 后进入 dangerouslySetInnerHTML。如果上游模型输出、选区内容诱导或其它 QA 消息源带入恶意 HTML,代码会在 QA WebView 的 DOM 中渲染未净化内容。

该风险被以下配置放大:

  • withGlobalTauri: true
  • security.csp: null
  • read_credential 等 Tauri command 暴露给前端

结果是:一旦 QA WebView 出现可执行 HTML/事件属性注入,攻击面可能从普通 XSS 升级为读取 ASR / LLM API Key 等本地敏感数据。

代码证据

  • openless-all/app/src/pages/QaPanel.tsx:405-408marked.parse(message.content, { async: false })
  • openless-all/app/src/pages/QaPanel.tsx:433-438:最终 assistant 气泡 dangerouslySetInnerHTML
  • openless-all/app/src/pages/QaPanel.tsx:445-460:streaming answer 同样使用 dangerouslySetInnerHTML
  • openless-all/app/src-tauri/tauri.conf.json:13withGlobalTauri: true
  • openless-all/app/src-tauri/tauri.conf.json:68-70csp: null
  • openless-all/app/src-tauri/src/commands.rs:131-134read_credential 返回凭据值

建议修复

  • QaPanel.tsx 中对 marked 输出做严格 allowlist 净化,例如 DOMPurify。
  • 如果 QA 不需要 raw HTML,优先禁用 / 转义 markdown 中的 HTML,只保留安全 markdown 子集。
  • 为 QA 渲染增加回归测试:HTML 标签、事件属性、危险 URL 都必须变成 inert 输出。
  • 后续可单独开 issue 收紧 CSP / Tauri command capability;本 issue 的最小修复目标是先消除 QA markdown 注入点。

验收标准

  • assistant 消息中的 HTML/event attribute 不会以可执行形式进入 DOM。
  • streaming answer 与最终 answer 使用同一套安全渲染路径。
  • 普通 markdown 能正常显示:段落、列表、代码块、加粗、链接。
  • 危险链接协议、内联事件、脚本相关标签被移除或转义。
  • 增加覆盖恶意 markdown/HTML 的最小回归用例。

关联

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingpriority: highHigh priority

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions