Skip to content

feat: PDF 匯出包含設定檔內容;前端 escapeHtml 型別繞過修補 - #22

Merged
Cody8722 merged 2 commits into
releasefrom
develop
Sep 8, 2026
Merged

Cody8722 merged 2 commits into
releasefrom
develop

Conversation

@Cody8722

@Cody8722 Cody8722 commented Sep 8, 2026

Copy link
Copy Markdown
Owner

Summary

  • PDF 隱藏資料改為包含設定檔內容:匯出的 PDF 隱藏資料從只有班表本身,改成 { schedule, settings }(連同人員/勤務設定)。匯入時若偵測到 settings,會詢問要套用到目前設定檔還是建立新設定檔;改版前只有班表陣列的舊格式 PDF 仍正常相容。
  • 前端 escapeHtml 型別繞過修補:延續上一輪後端 XSS 修補,前端共用的 escapeHtml() 有同一種型別繞過瑕疵(陣列/物件會跳過轉義),已比照後端做法修掉並補上回歸測試。目前經後端驗證的資料不會觸發,屬防禦性補強。

Test plan

  • 前端 97/97 測試通過
  • 後端 348/348 測試通過
  • CI(backend/frontend/E2E 三個 job)全綠
  • 在隔離的 scheduleApp_test 資料庫上,用真實 Root+HKDF 加密產生測試 PDF,透過瀏覽器實際上傳匯入,驗證「套用到目前設定檔」與「建立新設定檔」兩條路徑皆正確運作,中文內容正確還原

🤖 Generated with Claude Code

https://claude.ai/code/session_0117v1Qxx7foQEH4cd6pfnLS

Cody8722 and others added 2 commits September 8, 2026 01:35
昨天修後端 scheduleRenderer.js 的 escapeHtml() 型別繞過漏洞後,發現
frontend/src/utils/escapeHtml.js 是完全相同的舊版邏輯(只在
typeof unsafe === 'string' 時才轉義,陣列/物件原樣放行),被
settingsRenderer.js 等 12 個檔案共用來把資料塞進 innerHTML。

目前經過後端 validateSettings() 驗證的資料(task.name/person.name)
保證是字串,這條路徑還打不穿,所以不是已知可利用的漏洞;但這是同一類
設計缺陷的殘留,比照後端做法一併修掉,避免之後其他資料來源(例如
PDF 匯入還原到前端狀態的資料,不見得會重新過一次後端驗證)繞過。

修法跟後端一致:escapeHtml() 一律先 String() 轉字串再轉義(null/
undefined 仍原樣回傳)。新增 escapeHtml.test.js(10 個測試,含陣列/
物件繞過的回歸測試)。前端 93/93、後端 348/348 全數通過。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0117v1Qxx7foQEH4cd6pfnLS
改版前 buildKeywordsWithPayload() 只打包班表本身(exportData),完全
不含設定檔的人員/勤務設定,匯入 PDF 時只能還原班表,設定檔要自己重新
建。改成打包 { schedule, settings }(settings 取自匯出當下的作用中
設定檔),匯入時若偵測到 settings,用 showConfirm 問要套用到目前設定
檔還是(取消後)用 showInput 建立新設定檔,都套用/建立完後重抓一次
profiles 並重繪,讓左側 UI 跟後端同步。

splitPayload() 判斷新舊格式:Array.isArray(data) 為 true 視為改版前
的舊格式(純班表陣列,沒有 settings 可還原,只還原班表),維持向下
相容,舊 PDF 不需要重新匯出。

後端不需要改動——/api/pdf-payload/encrypt、decrypt 對內容格式無感知
(整包 JSON 加解密);套用/建立設定檔都是走既有的
PUT /api/profiles/:name、POST /api/profiles,兩者都已經有
validateSettings() 做嚴格型別驗證,不會因為 PDF 內嵌的資料繞過驗證。

新增 pdfImport.test.js(4 個測試,涵蓋新舊格式判斷)。並在隔離的
scheduleApp_test 資料庫上完整實機測試:用真實 Root+HKDF 加密產生
測試 PDF,透過瀏覽器實際上傳匯入,驗證「套用到目前設定檔」與
「建立新設定檔」兩條路徑都正確運作、班表與設定檔內容(含中文)都
正確還原。前端 97/97 測試通過。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0117v1Qxx7foQEH4cd6pfnLS
@Cody8722
Cody8722 merged commit 9ed195f into release Sep 8, 2026
6 checks passed
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.

1 participant