2026-07-25 資安三工具重掃 — MEDIUM 級分析報告

執行時間:2026-07-25 03:57~04:30(排程任務)。掃描範圍:BE + FE,工具 trivy / semgrep / SonarQube。 對照基準:2026-07-24 修正後掃描(handoff §1)。掃描期間 runner session 同時在工作, 本次結果已含 runner 的 Sonar 清理與 TipTap 收斂 commits(BE 至 547471d6、FE 至 1dd0aba)。

1. 前後對比總表

指標 前次(07-24 修正後) 本次(07-25) 說明
BE Trivy 總計 6 2(MEDIUM ×2) jedi 18 套件發版生效:flask LOW×2 / marshmallow / dotenv 4 條歸零 ✅
BE Trivy HIGH 0 0 維持
FE Trivy MEDIUM+ HIGH 18 HIGH 17 + MEDIUM 13 preact 已解 ✅、quill 主 lock 已拔 ✅;殘留大宗是 docs/reference/ultima-vue 範本 + 間接依賴(見 §3)
Semgrep BE ERROR 38(修正前)→ 預期歸零 9 全部是 avoid-sqlalchemy-text 常數插值,判誤報(見 §4)
Semgrep FE ERROR 1 0
Sonar BE 總 issues 875 825 runner S1481/S1192 清理生效
Sonar FE 總 issues 1065 757 runner S2486/a11y/TipTap 清理生效
Trivy secret(版控內) 0 1 個真實外洩(jedi-issue wheel) ⚠️ 新發現 P1,見 §2

2. ⚠️ 新發現 P1:jedi-issue 套件 wheel 內含 .env(GitHub/GitLab PAT)

Trivy secret 掃描在 .venv/lib/python3.11/site-packages/jedi_issue/.env 掃到 github-pat + gitlab-pat。追查結果:

  • 源頭是 ~/Projects/Jedicogy/module/jedi-python-package/jedi-issue/jedi_issue/.env——位於套件目錄內,被 poetry packages = [{ include = "jedi_issue" }] 整包打進 wheel
  • 該檔在 jedi monorepo git 內被版控(初始 commit b740989 就進來了),含 GITLAB_PRIVATE_TOKENGITHUB_PRIVATE_TOKEN 實值
  • 歷次發版(至少 0.0.14、0.0.15)的 wheel 與 sdist 都含此檔,已散佈在 Nexus 上,所有裝過 jedi-issue 的環境 site-packages 內都有一份
  • 本機 .venv 內那份就是安裝時帶進來的

處置(已開 Notion case,需 user/團隊執行 token revoke)

  1. Revoke 該 GitLab PAT + GitHub PAT(token 持有人處理;從 git log 看是 James 初始 commit 帶入)
  2. jedi-issue 移除 jedi_issue/.env(改 .env.sample placeholder 放套件外)+ .gitignore 補排除
  3. 重新發版(0.0.16)、主專案升 pin;Nexus 上舊版 wheel 視管理需要決定是否下架
  4. 其餘 17 套件已抽查無同樣問題(僅 jedi-issue 的 .env 在套件目錄內)

其餘 trivy secret 8,484 條全部位於未版控路徑(.envlog/pki/reports/.venv),大宗是 log 檔內的 JWT token(8,478 條),屬本地開發產物,非外洩。

3. Trivy MEDIUM+ 全清單與修正方式

BE(2 條,皆 MEDIUM)

套件 現裝 修復版 CVE 判定與修法
pytest 8.4.2 9.0.3 CVE-2025-71176 新出現(8.4.2 是昨夜剛升的目標版,此 CVE 需跨大版 9.x)。被 jedi 18 套件 pytest>=8.4,<9 卡住,修復需再放寬一輪到 <10;純 dev 工具、不進 runtime image → 已開 case 等裁決(再發版一輪 vs 風險接受)
weasyprint 68.1 CVE-2026-49452 上游 no-fix(CSS injection),既有裁決風險接受,不重複開 case

FE — 真實專案依賴(package-lock.json

套件 現裝 修復版 Severity 引入鏈 修法
linkify-it 5.0.0 5.0.2 HIGH ×2 @tiptap/pm → prosemirror-markdown → markdown-it(runtime npm overrides
markdown-it 14.1.0 14.2.0 MEDIUM ×2 同上(runtime npm overrides
socket.io-parser 4.2.4 4.2.6 HIGH socket.io-client(runtime npm overrides
underscore 1.13.7 1.13.8 HIGH mammoth(runtime npm overrides
minimatch 5.1.6 5.1.8+ HIGH ×3 mocha/eslint(dev) npm overrides
brace-expansion 2.0.2 2.1.2 HIGH + MEDIUM eslint/mocha(dev) npm overrides
picomatch 2.3.1 2.3.2 HIGH + MEDIUM mocha/chokidar(dev) npm overrides
serialize-javascript 6.0.2 7.0.3 HIGH + MEDIUM mocha(dev) npm overrides
uuid 10.0.0 / 8.3.2 11.1.1+ MEDIUM direct dep ^10.0.0 + cypress/mochawesome direct 升 ^11、間接 overrides

→ 已開 case「FE 依賴 CVE 第二輪」,一次 overrides + uuid 升版 + build 驗證。

FE — docs/reference/ultima-vue-6.4.0/(範本殘留,不修)

brace-expansion / glob / minimatch 9.0.5 / picomatch / postcss / nanoid / yaml / quill 全數只出現在此參考範本的 lock 檔。前次已裁決:範本非建置產物、不進 bundle,維持不修(若要歸零可整目錄刪除或加 .trivyignore,留給 CI case 一併決定)。

4. Semgrep 判定

BE ERROR ×9 — 全部 avoid-sqlalchemy-text,判誤報

位置:infra/oscal/repository/ssp_control_implementation_query.py(×3)、resource_library_query.py(×3)、app/oscal/service/resource_library_app_service.py(×2)、app/project/service/project_start_app_service.py(×1)。 逐條看過:f-string 插值的都是模組常數(表名 _MF、固定 SQL 片段 xml_expr/join_trans),使用者輸入全走 bound parameters(:uid 等)。無注入面。不開 case;若要消音可加 # nosemgrep 註記,屬美化。

BE WARNING ×19 — 逐類判定

規則 條數 判定
non-literal-import 7 誤報——模組註冊機制(REGISTERED_APPS 動態 import)與 scripts,來源是程式內常數
python-logger-credential-disclosure 4 誤報——逐條看過,log 內容只有 tenant_id / job_id,無憑證值(drive_sync_worker / webhook / token_manager)
insecure-hash-algorithm-sha1 4 誤報——sha1 用於 diff identity key(party 配對指紋),非密碼學用途;要消音可換 sha256(一行),非必要
missing-integrity 2 低風險——scripts/evidence/classify/prototype-ui/ 內部原型的 CDN script 無 SRI,不進產品
make-response-with-unknown-content 2 誤報——SSP/MF 匯出 route 回傳檔案 bytes,本來就是二進位 response

FE — ERROR 0;WARNING ×14 判定

  • avoid-v-html ×8:逐條驗證——ReferenceDocumentList 過 DOMPurify ✅、diff 元件 renderDiff()escapeHtml() ✅、ControlImplSection/ObjectiveDiffRow 同 diff 家族 escape ✅。唯一留意點:App.vue:11 toast message.detail 直接 v-html——目前 detail 全部來自 i18n 常數與程式組字串,無使用者輸入路徑,判低風險;日後若把 BE 回傳訊息直塞 toast 需先 sanitize(已記入報告,不開 case)
  • path-join-resolve-traversal ×4:build-time 腳本 sync-translations.js,非 runtime,誤報
  • insecure-object-assign ×2:useSurveyMock.js mock 資料組裝,誤報

5. Sonar 判定(VULNERABILITY + BLOCKER/CRITICAL bug)

BE:VULN 34 條,無需修 code 的真實洞

  • S5332 http:// ×26(MINOR):全是 XML namespace 常數(http://camunda.org/schema/...)與內網 dev 預設 URL,非實際不安全連線,誤報
  • S4502 CSRF disabled ×2(CRITICAL):core/app_factory.py:35 + backfill script——本系統走 JWT header 認證(無 cookie session),CSRF 保護不適用,屬設計決策。風險接受,於此報告留檔
  • S2245 pseudorandom ×5(MAJOR):captcha 圖形的隨機顏色/字型(視覺雜訊非安全用途)+ common_util.py:117,誤報
  • Web:S5247 autoescape ×1(MAJOR):project_summary_report_template.html——上游已在 07-24 arc 加 bleach sanitize(summary 富文本),模板層 autoescape off 是刻意(渲染已消毒 HTML),風險已控
  • BLOCKER/CRITICAL bug:0 條(前次 7 條 S3516 是 CODE_SMELL 類,仍在 backlog 禁區內不動)

FE:VULN 8 條全誤報;CRITICAL bug 7 條(新發現,已開 case)

  • VULN:S2245 ×6(sessionShare tab id 前次已判誤報、_archived 死碼、demo dashboard、DynamicPrimeComponent key 生成)+ S5332 ×2(BPMN XML namespace 常數),全誤報
  • CRITICAL bug 7 條是重掃新發現(runner Round 1 修掉 duplicate id "key" 與 AppMenuItem 後,同檔還有同型別 bug):
    • Web:S7930 duplicate id ×5:ComplianceFrameworkVersionManage.vue 868/880/892(version / release_date / publish_status)、ModuleFrameItems.vue:488(frequency)、WorkflowSetupEditor.vue:860(actionInfo)
    • javascript:S930 傳參給無參函式 ×2:ModuleFrameItems.vue:129WorkflowSetupEditor.vue:106(AppMenuItem 同族 bug) → 已開 case(含 S930 修前必讀 source 護欄,比照 AppMenuItem 教訓)

6. 修正生效驗證(對照 07-24/25 已修內容)

修正 驗證結果
jedi 18 套件發版(flask 3.1.3 / marshmallow 3.26.2 / dotenv 1.2.2 / pytest 8.4.2) ✅ 4 條 CVE 從 BE trivy 消失(pytest 另冒 CVE 需 9.x,見 §3)
FE preact 升版(runner) ✅ trivy 無 preact 條目
TipTap 收斂拔 quill + ckeditor5(runner) ✅ 主 lock 無 quill/ckeditor5 CVE(僅 docs/reference 範本殘留)
BE Sonar S1481/S1192 清理(runner) ✅ 總數 875 → 825
FE Sonar S2486/a11y 清理(runner) ✅ 總數 1065 → 757

7. 本次開立的 Notion case

Case 內容 優先
[P1][資安] jedi-issue wheel 內含 .env(GitHub/GitLab PAT) revoke + 套件移除 .env + 重發版 P1
[資安] FE 依賴 CVE 第二輪(runtime overrides + uuid 升版) linkify-it / markdown-it / socket.io-parser / underscore / dev 依賴 overrides P2
[討論][資安] BE pytest 9.0.3(CVE-2025-71176)——jedi pin 再放寬 vs 風險接受 需 user 裁決(dev 工具、要再發版一輪) P3
[優化] FE Sonar 重掃新增 CRITICAL bug ×7 duplicate id ×5 + S930 ×2 P2

不重複開(既有 case / 裁決涵蓋):weasyprint no-fix、docs/reference 範本殘留、CSRF 設計決策、S3776/S3516 backlog 禁區。