2026-07-25 資安掃描 arc 第二棒收官 — 換 session Handoff

項目 內容
緣由 資安 arc 第二棒(剩餘線)已全部執行完畢:jedi 兩輪發版、jedi-issue 憑證外洩處置、半夜重掃 + MEDIUM 分析、runner 派工 4 案完結、掃描基建三項調整。換 session 交接剩餘驗收與行政收尾
Branch BE / FE / jedi monorepo 皆 main,working tree 全乾淨
接手前必讀 本文件全讀 → 前一棒 handoff 2026-07-24-security-scan-arc-session-handoff.md(背景)→ Notion 搜「資安」
預估時間 剩餘皆為 user 驗收/裁決後的零星動作,無大工程

🧭 原始需求 / WHY

User(雷門)對 BE + FE 跑三工具資安掃描(semgrep/trivy/SonarQube),目標:HIGH 歸零、憑證外洩處置完畢、剩餘項條條有歸屬。07-24 第一棒完成主體;本棒(07-25)接「剩餘線」:user 追加指示「MEDIUM 也要修掉」+「每次掃描結果要留存」。

大圖:這是掃描常態化進 GitLab CI 前的手動 baseline 期。CI/CD case 已建但 user 明示先不做

目前達成狀態(本棒結束時)

  • BE trivy:只剩 weasyprint CVE-2026-49452 一條(上游 no-fix,風險接受)——從 arc 起點 26 條到此
  • FE trivy:0 條(含 HIGH/MEDIUM 全清 + docs/reference 範本排除)
  • FE Sonar BLOCKER/CRITICAL bug:0 條;semgrep FE ERROR:0 條
  • 兩波憑證外洩(Telegram/Discord + jedi-issue wheel PAT)全處置

§0 接手讀序

  1. 🔒 先讀本文件 🧭 + §1(本棒成果)+ §3(剩餘工作),能答冷接自檢再動
  2. 前一棒 handoff:docs/features/security-scan-2607/handoff/2026-07-24-security-scan-arc-session-handoff.md(arc 全貌 + 教訓)
  3. 重掃分析:docs/features/security-scan-2607/2026-07-25-rescan-medium-analysis.md(MEDIUM 級逐條判定)
  4. Notion 任務清單(data source id 23c346da-4cd0-8041-955e-000bb6976dd2)搜「資安」——即時狀態以 Notion 為準

冷接自檢 4 問: ① 本 arc 的 MEDIUM 目標達成了嗎?(BE 剩 weasyprint 1 條 no-fix、FE 歸零——達成,「修掉 MEDIUM」的指示已完成) ② jedi 套件這棒發了幾輪版、為什麼兩輪?(第一輪 18 套件解 flask/marshmallow/dotenv/pytest 4 條 CVE;pytest 8.4.2 隨即冒新 CVE 要 9.x 被 <9 擋住,user 裁決「一次解決」→ 第二輪 18 套件放寬 <10 + pytest 9.0.3。另 jedi-issue 單獨發了 0.0.16 移除 .env) ③ 掃描報告放哪、規則是什麼?(docs/security-reports/YYYY-MM-DD/ 日期資料夾制,本機留存不入版控、僅 README force-add;禁止根目錄固定檔名覆蓋——07-24 兩版就是這樣丟的) ④ SonarQube 在哪?(192.168.50.171:9000,07-25 從 localhost 搬家;token 是 ~/.zshrc SONAR_USER_TOKEN,bash 下要 grep 抽值不能 source)

§1 本棒成果(2026-07-25)

jedi-* 套件(三次發版動作,全部 publish Nexus 成功)

  1. 第一輪 18 套件(monorepo c6188f7):dotenv>=1.2.2 / pytest>=8.4;jedi-common 另放寬 Flask>=3.1.3 / marshmallow>=3.26.2 → BE 4 條 CVE 歸零
  2. jedi-issue 0.0.16d6a8d09):移除打包進 wheel 的 jedi_issue/.env(含上古已 revoke 的 GitLab/GitHub PAT,Notion P1 case 已 Done)。正式 token 介面是 DB ISSUE_INTEGRATE_CONFIG(system_configs 表)config 注入,該 .env 只是被套件 __init__.pyload_dotenv() 意外載入——拔除零功能影響
  3. 第二輪 18 套件0bdadde):pytest pin 放寬 <10(user 裁決一次解決),BE pytest 升 9.0.3
  • 最終版號:common 0.0.29 / auth 0.1.33 / oscal-v2 2.2.3 / issue 0.0.17 / survey 0.0.32 / flow-engine 0.0.34 等(詳 monorepo git log)

BE 修正

  • pyproject 三波:jedi 全套升 pin ×2 + pytest 9.0.3(092c69af)+ Flask-Cors 6.0.0d338b5ab,升 flask 3.1.3 後 trivy 新入列 3 條 MEDIUM CVE-2024-6839/6844/6866,CORS preflight 驗證過)

FE(runner session 完成,全部已 user 驗收標 Done)

  • CM-879 依賴 CVE 第二輪:overrides +9 鍵(範圍鍵防 eslint 舊鏈拉壞)+ uuid ^11(a848f4a
  • CM-881 Sonar CRITICAL ×7:duplicate id ×5 改後綴 + S930 ×2 讀 source 確認後移除多傳引數(aa01edd
  • 另 runner 完成:preact 升版、TipTap 收斂(quill+ckeditor5 已拔)、S2486/a11y 批次、BE Sonar 安全四桶

掃描基建(user 三項指示全落地)

  1. 報告留存docs/security-reports/YYYY-MM-DD/ 日期資料夾制(先建於 repo 根、後奉命搬入 docs/),方案 A 本機留存,README force-add 入版控(BE 47e66bf6 / FE 15fdcb9)。gitignore 的 ! 例外會被目錄排除蓋過,加 README 要 git add -f
  2. docs/reference 排除:FE trivy.yaml9a2b51c)——sonar/semgrep 本來就不掃
  3. SonarQube 搬家 171:9000(BE 00b591ad / FE 35de2c6):scripts/sonar_scan.sh 首次入版控;新 server 兩專案由首掃自動建立

Final 收官掃描(07-25 上午,三工具 ×2 repo 全跑)

結果存 docs/security-reports/2026-07-25/(BE/FE 各三檔)。數字:BE trivy 1(weasyprint)/ FE trivy 0 / FE semgrep ERROR 0 / FE Sonar CRITICAL bug 0 / BE Sonar 825 issues(VULN 34 全誤報或已控——判定依據在重掃分析文件 §5)/ FE Sonar 750。

§2 本棒教訓(別重蹈)

  1. zsh echo $resp | jq 會弄壞 JSON(echo 吃跳脫字元)——Sonar API 匯出一律 curl 落檔再 jq
  2. bash 下 source ~/.zshrc 不生效——token 用 grep -E '^export SONAR_USER_TOKEN=' ~/.zshrc | sed 's/.*=//; s/"//g'
  3. poetry run dotenv -f 參數不存在——BE 起服務標準式:nohup poetry run python -c "from dotenv import load_dotenv; load_dotenv('.env'); import runpy; runpy.run_path('main_app.py', run_name='__main__')" &
  4. 升版會揭新洞:flask 3.1.0→3.1.3 讓 trivy 把 Flask-Cors 3 條 MEDIUM 掃出來;pytest 8.3.4→8.4.2 冒新 CVE 要 9.x。升版後必重掃驗證,別假設「升了就乾淨」
  5. runner 紅線含「永不動 jedi/發版」——jedi 發版類 case 一律主 session 做,別派 runner
  6. gitignore ! 例外 + 目錄排除docs/security-reports/* + !.../README.md 組合下 git add 仍被擋,force-add 才進得去

§3 剩餘工作

§3.1 等 user 驗收(Notion「修正待驗證」,勿代標 Done)

  • CM-873 BE Sonar 品質債四桶(runner 清完 S1481/S1192,S125/S1172 整桶跳過有記錄)
  • CM-874 FE Sonar 品質債(a11y 批次等)
  • CM-876 TipTap 收斂(公告/兩回饋表單/摘要報告四處手測)

§3.2 push 狀態(⚠️ 待確認)

本 session 尾聲觀測到三 repo 的本地 origin/main ref 已等於 HEAD——Claude 無 GitLab 憑證(fetch/push 都會 could not read Username),所以極可能是 user 已自行 push 過。下一棒 pre-flight 跑 git status -sb 確認;若顯示 ahead 則仍未推,push 永遠等 user 明示。

§3.3 部署對齊(user/運維執行,Claude 提醒即可)

  • classify docker image 各主機 rebuild(Dockerfile 加了 USER)
  • 分類器 job 目錄 /tmp→~/.cm-jobs,部署 -v 掛載同步
  • 部署機 poetry update 才吃得到 jedi 新版(兩輪發版 + Flask-Cors/pytest 升版)
  • Nexus 舊版 jedi-issue wheel(≤0.0.15 含已 revoke token)是否下架——user 說 token 已死不急

§3.4 未來線

  • CI/CD case(Notion 有完整架構)——user 明示先不做,等環境準備
  • 掃描報告留存屆時改 GitLab CI artifact(README 已預告)
  • BE pytest 環境修復(126 collection errors)——既有問題,值得開 case 未開

§4 開工順位

  1. 跑 §6 pre-flight
  2. 等 user 指示(驗收結果處理 / 新任務)——本 arc 無 pending 工程,不要自己找事做
  3. 若 user 要再掃:照 docs/security-reports/README.md 的指令備忘,輸出進當天日期資料夾

§5 該讀的檔案

  • docs/features/security-scan-2607/2026-07-25-rescan-medium-analysis.md — MEDIUM 逐條判定(semgrep 誤報依據 / Sonar VULN 34 條判定 / CSRF 設計決策)
  • docs/security-reports/README.md(BE,政策 owner)— 留存慣例 + 各工具掃描指令
  • docs/claude/notion-bug-loop-runner.md — runner 手冊(紅線清單)
  • memory reference_security_scan_tooling — SonarQube 座標 / token / 留存慣例

§6 Pre-flight(接手必跑)

cd ~/Projects/Billows/Audit-Manager/compliance-manager-be
git log --oneline -6   # 應見 00b591ad / 47e66bf6 / b26fcef7 / d338b5ab / 092c69af / 672413a0
git status -sb          # main 乾淨;若顯示 ahead N 代表未 push
ls docs/security-reports/2026-07-25/   # 應有 trivy/semgrep/sonar 三檔
cd ~/Projects/Billows/Audit-Manager/compliance-manager-fe
git log --oneline -4   # 應見 35de2c6 / 15fdcb9 / 9a2b51c / 8295248
cd ~/Projects/Jedicogy/module/jedi-python-package
git log --oneline -3   # 應見 0bdadde / d6a8d09 / c6188f7
# BE 起服務(改過 service/依賴後):
# cd BE repo && nohup poetry run python -c "from dotenv import load_dotenv; load_dotenv('.env'); import runpy; runpy.run_path('main_app.py', run_name='__main__')" > /dev/null 2>&1 &
# curl -s -X POST localhost:8000/api/1.0/login -H 'Content-Type: application/json' -d '{}'  # 400=正常

§7 Verify 本棒確實 close

cd ~/Projects/Billows/Audit-Manager/compliance-manager-be
jq -r '.Results[] | (.Vulnerabilities // [])[] | "\(.Severity) \(.PkgName)"' docs/security-reports/2026-07-25/trivy-backend.json
# 應只有: MEDIUM weasyprint
jq '[.Results[].Vulnerabilities // [] | .[]] | length' ~/Projects/Billows/Audit-Manager/compliance-manager-fe/docs/security-reports/2026-07-25/trivy-frontend.json
# 應為: 0
python -c "import pytest, flask; print(pytest.__version__)"   # 9.0.3
ls .venv/lib/python3.11/site-packages/jedi_issue/ | grep -c .env   # 0

§8 行為規範重要提醒

  • 不切 branch / 顯式 git add 禁 -am / push 等 user 明示(§3.2 先確認狀態)
  • BE 起服務 = main_app.py(8000)+ load_dotenv 包裝(§2.3 標準式);kill -9 清殘留
  • jedi-* 異動需 user 明示;發版絕不自動推 Nexus;runner 永不碰 jedi
  • 掃描輸出進 docs/security-reports/YYYY-MM-DD/,禁根目錄固定檔名
  • 大檔(trivy json 27MB / sonar issues 2.7MB)一律 jq,勿整檔 Read
  • user 說「先不用/等等」就停手

§9 收尾流程

本 arc 主體 + 剩餘線皆已收。CM-873/874/876 user 驗過標 Done 即全案終結;屆時若 user 下令「總結」,走 closing-and-handoff 的完整收尾(SUMMARY + memory + spec 盤點——資安修正無頁面行為變更,spec 更新預期不適用)。

§10 不在本期 scope

  • CI/CD 實作(user 明示擱置)
  • FE Dockerfile nginx USER(等部署決策)
  • BE pytest 環境修復(126 collection errors)
  • git history rewrite(憑證已全 revoke,不值)
  • FE App.vue:11 toast v-html(判低風險留檔,重掃分析 §4 有記錄——若日後 BE 訊息直塞 toast 需先 sanitize)

§11 本棒 commits(07-25,時序)

BE672413a0(jedi-issue 0.0.16) 092c69af(pytest 9.0.3+jedi 二輪) d338b5ab(Flask-Cors 6.0.0) b26fcef7(留存 README) 47e66bf6(搬 docs/) 00b591ad(Sonar 搬家) + 969983f0(重掃分析) 66d160a9(runner handoff) + runner 的 loop log/清理串 FEa848f4a(CM-879) aa01edd(CM-881) 8295248(CM-882-884 回饋附件) 9a2b51c(trivy.yaml) 15fdcb9(搬 docs/) 35de2c6(Sonar 搬家) + runner 的 TipTap/S2486 串 jedi monorepoc6188f7(一輪) d6a8d09(issue .env) 0bdadde(二輪)

§12 給 fresh session 的超短 prompt

請讀 docs/features/security-scan-2607/handoff/2026-07-25-security-arc-final-session-handoff.md,
先答 §0 冷接自檢 4 問(不跳過 WHY),再跑 §6 pre-flight + §7 verify。
本 arc 工程已全部完成,你的工作是待命:等我對 CM-873/874/876 的驗收結果、或新指示。
注意:push 狀態見 §3.2 先確認;BE 起服務用 §2.3 的 load_dotenv 標準式(port 8000)。