fix(security): 跨网点病历存储型 XSS 双侧消毒(SEC-02 / P1) #223

Open
redxin wants to merge 1 commit from fix/p1-security-2026-06-23 into claude/frosty-knuth-efd579
Owner

P1 安全修复:跨网点病历存储型 XSS(SEC-02)

全量系统测试(PR #222 报告 §六 SEC-02)发现并经监工代码核实的 P1:他院病历只读调阅经 dangerouslySetInnerHTML 渲染 RichTextEditor(execCommand)产出的原生 HTML,此前全前端无消毒 → 恶意网点可在病历 content 注入 <script> / <img src=x onerror=...>,他院跨网点查阅时在其会话执行(存储型、跨租户 XSS)。

改动

  • 新增 utils/sanitizeHtml.ts:DOMPurify 白名单消毒(仅放行富文本排版标签 + 安全属性,剥离 script/事件处理器/危险协议)。
  • 应用于全部 dangerouslySetInnerHTML 渲染用户 HTML 处:
    • CrossClinicRecordsSection.tsxCrossClinicTab.tsx(跨网点只读渲染点)
    • RichTextEditor.tsx 载入已存 HTML 时(防御纵深)
  • 依赖:dompurify@^3.4.11

门禁

  • npm run typecheck 0 错 · vitest 227 passed · vite build 通过
  • 运行时:210 重部署后 Chrome 注入实测确认脚本不再执行(见评论/报告)

范围说明

  • base = claude/frosty-knuth-efd579(PR#221),折入前端重构 PR;CrossClinicRecordsSection/RichTextEditor 与 main 一致,故 main 生产侧同问题随 #221 合入修复。
  • P1-2(患者姓名静态加密)未含:经核实 full_namepatient:profile:read 开放是后端注释记录的产品决策;真缺口=姓名静态加密,作为独立迁移任务排期(SEC-01 降为待排期硬化)。

🤖 Generated with Claude Code

## P1 安全修复:跨网点病历存储型 XSS(SEC-02) 全量系统测试(PR #222 报告 §六 SEC-02)发现并经监工代码核实的 P1:他院病历只读调阅经 `dangerouslySetInnerHTML` 渲染 `RichTextEditor`(execCommand)产出的**原生 HTML**,此前全前端无消毒 → 恶意网点可在病历 `content` 注入 `<script>` / `<img src=x onerror=...>`,他院跨网点查阅时在其会话执行(**存储型、跨租户 XSS**)。 ### 改动 - 新增 `utils/sanitizeHtml.ts`:DOMPurify 白名单消毒(仅放行富文本排版标签 + 安全属性,剥离 script/事件处理器/危险协议)。 - 应用于全部 `dangerouslySetInnerHTML` 渲染用户 HTML 处: - `CrossClinicRecordsSection.tsx`、`CrossClinicTab.tsx`(跨网点只读渲染点) - `RichTextEditor.tsx` 载入已存 HTML 时(防御纵深) - 依赖:`dompurify@^3.4.11` ### 门禁 - `npm run typecheck` 0 错 · `vitest` 227 passed · `vite build` 通过 - 运行时:210 重部署后 Chrome 注入实测确认脚本不再执行(见评论/报告) ### 范围说明 - base = `claude/frosty-knuth-efd579`(PR#221),折入前端重构 PR;`CrossClinicRecordsSection`/`RichTextEditor` 与 main 一致,故 main 生产侧同问题随 #221 合入修复。 - **P1-2(患者姓名静态加密)未含**:经核实 `full_name` 对 `patient:profile:read` 开放是后端注释记录的产品决策;真缺口=姓名静态加密,作为独立迁移任务排期(SEC-01 降为待排期硬化)。 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fix(security): 跨网点病历存储型 XSS 双侧消毒(SEC-02/P1)
Some checks failed
CI / Frontend (Tauri/TS) (pull_request) Has been cancelled
CI / Backend (Go) (pull_request) Has been cancelled
9c9d8e7138
他院病历只读调阅经 dangerouslySetInnerHTML 渲染 RichTextEditor 产出的原生 HTML,
此前全前端无消毒→恶意网点可在病历 content 注入脚本在他院会话执行(存储型跨租户 XSS)。
新增 utils/sanitizeHtml(DOMPurify 白名单,剥离 script/事件处理器/危险协议),应用于:
- CrossClinicRecordsSection.tsx / CrossClinicTab.tsx 跨网点只读渲染点
- RichTextEditor 载入已存 HTML 时(防御纵深)
门禁: npm run typecheck 0 错 / vitest 227 passed。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Some checks failed
CI / Frontend (Tauri/TS) (pull_request) Has been cancelled
CI / Backend (Go) (pull_request) Has been cancelled
This pull request can be merged automatically.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin fix/p1-security-2026-06-23:fix/p1-security-2026-06-23
git switch fix/p1-security-2026-06-23

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch claude/frosty-knuth-efd579
git merge --no-ff fix/p1-security-2026-06-23
git switch fix/p1-security-2026-06-23
git rebase claude/frosty-knuth-efd579
git switch claude/frosty-knuth-efd579
git merge --ff-only fix/p1-security-2026-06-23
git switch fix/p1-security-2026-06-23
git rebase claude/frosty-knuth-efd579
git switch claude/frosty-knuth-efd579
git merge --no-ff fix/p1-security-2026-06-23
git switch claude/frosty-knuth-efd579
git merge --squash fix/p1-security-2026-06-23
git switch claude/frosty-knuth-efd579
git merge --ff-only fix/p1-security-2026-06-23
git switch claude/frosty-knuth-efd579
git merge fix/p1-security-2026-06-23
git push origin claude/frosty-knuth-efd579
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
redxin/DentalFlow!223
No description provided.