# 2026-07-24 資安掃描修正 arc — 換 session Handoff

| 項目 | 內容 |
|------|------|
| 緣由 | 資安掃描修正 arc 主體已完成並經 user 手測驗收，context 滿了換 session。剩餘為 runner 派工、jedi-* 升版解殘留、CI/CD 化三條後續線 |
| Branch | BE / FE 皆在 `main`（未 push，見 §11） |
| 接手前必讀 | 本文件全讀 → Notion 任務清單「資安掃描」相關 case |
| 預估時間 | 依接手任務而定（見 §4 開工選項） |

## 🧭 原始需求 / WHY

User（雷門）對 BE（compliance-manager-be）與 FE（compliance-manager-fe）跑了三工具資安掃描（semgrep / trivy / SonarQube），要求：**分析報告 → 分診真偽 → 開 Notion case 追蹤 → 修正**。

**目標狀態**：HIGH 級漏洞歸零、憑證外洩處置完畢、剩餘項每條有明確歸屬（誰卡住、何時解）。**此目標已在本 session 達成**——本 handoff 的意義是把「剩餘三條後續線」與「本 arc 的環境知識」交給下一棒，不是接手修 bug。

**大圖**：這是 Guidant AI 產品的第一次系統性資安健檢。長期方向是把掃描常態化進 GitLab CI（secret gate 擋憑證、每週依賴健檢），本次手動掃描是 baseline。

## §0 接手讀序

1. 🔒 **先懂需求**：讀完本文件 🧭 + §1（成果總表）+ §3（剩餘工作），能答出下方自檢 4 問再動手
2. Notion 任務清單（DB id `23c346da-4cd0-8041-955e-000bb6976dd2`）搜「資安」——12 條 case 的即時狀態以 Notion 為準
3. 若接 runner 派工線 → 讀 §3.1；若接 jedi 升版線 → 讀 §3.2；若接 CI/CD 線 → 讀 Notion CI case（內含完整架構與雷門準備清單）

**冷接自檢**：① 這個 arc 解決了什麼？（兩組憑證外洩 + 86 條 CVE + 程式碼硬化）② 為什麼還有 6 條 BE CVE 殘留？（jedi-* 硬 pin，需 user 明示才能動）③ commits 推了沒？（**全部未 push**）④ BE 正確啟動方式？（`main_app.py` port 8000，**不是** main_socketio）

## §1 本 arc 成果（已全部 user 驗收，Notion 標 Done）

**掃描前後對比**：

| 指標 | BE | FE |
|------|-----|-----|
| Trivy HIGH | 15 → **0** | 83 → 18（殘留=間接依賴+docs/reference 範本+preact） |
| Trivy 總計 | 26 → 6 | 202 → 35 |
| Semgrep ERROR | 38 → 預期歸零（未重掃複驗） | 1 → 1（FE Dockerfile USER，待部署決策） |
| 憑證外洩 | 2 組全部 revoke + 檔案清除 | — |

**修正內容速覽**：
- **P0 憑證**：Telegram token / Discord webhook（.env.sample/.env.test + conversation-history 15 檔）revoke + redact；FE `sonar-project.properties` 明文 admin 帳密移除（密碼已換，改 SONAR_TOKEN env var）
- **BE 硬化**：報告 PDF 匯出 bleach sanitize（summary 是 TipTapEditor 富文本）、BPMN 解析 6 處改 defusedxml（產生端不動）、上傳檔名 secure_filename、classify Dockerfile 非 root、CORS config 化收斂（dev=* / stg+prod=[WEBSITE_URL]）、分類器 job 目錄 /tmp→~/.cm-jobs（0o700）、workflow mapper 死碼修正（enum 透傳，**不可 .value**——下游 DTO 會再取一次）
- **BE 升版**：pillow 12.3.0 / lxml 6.1.1 / weasyprint 68.1 / eventlet 0.40.4
- **FE 修正**：camunda-api.js 死碼刪除（硬編內網 IP）、StorageConfigForm /tmp 預設改空 + 必填驗證接手
- **FE 升版**：axios 1.18 / dompurify 3.4.12 / vite 4→8（+@vitejs/plugin-vue 6）/ overrides 7 套；xlsx 孤兒依賴移除
- **gitignore**：兩 repo 加 `.scannerwork/` + `security-reports/`
- **裁決**：quill 風險接受（3 表單、輸出全過 v-dompurify-html、被 PrimeVue 3.53 鎖 1.x）→ 根治歸「TipTap 收斂」case

## §2 前次教訓（本 session 踩過的雷，別重蹈）

1. **BE 起服務用 `main_app.py`（port 8000）**，`main_socketio.py` 起的是 SOCKET_PORT 8002 非 API 入口——本 session 反覆起錯繞遠路。已寫 memory `feedback_be_entrypoint_main_app_port_8000`
2. **subagent 碰大檔必爆 context**：`docs/conversation-history/`、`security-reports/*.json`、`camunda_service.py`（2000+ 行）、`bpmn_generator.py`（2300+ 行）。派工單必帶「禁 Read 整檔，grep -n 定位 + sed 看片段」護欄——A1 連死兩次都是這個原因
3. **超長行檔案 grep 會靜默漏**：conversation-history 有單行數萬字元的檔，plain grep 無錯誤無輸出直接跳過，要用 `git grep` 或 `grep -a`
4. **agent 的修正要獨立復核**：A1 agent 把 mapper 改成 `model.status.value`，但下游 DTO（`app/flow_engine/dto/ext_workflow_execution_dto.py:71`）會再取 `.status.value`——盲收會讓所有 workflow 查詢炸 AttributeError。已改回 enum 透傳
5. **`pytest test/` 目前整包壞**：126 個 collection error（`ModuleNotFoundError: No module named 'app'`），是既有環境問題與本 arc 無關（stash 對照驗過）。BE 驗證改用煙測 + 起服務 + curl

## §3 剩餘工作（三條線，皆記錄在 Notion）

### §3.1 Runner 派工線（user 已同意方向，動工指引尚未寫入 case）

適合派 runner 自主處理的三條（user 拍板過「除 CI/CD 外可派 runner」）：
- **FE Sonar 品質債**（Notion「[優化] FE Sonar 品質債 backlog」）：a11y ~240 條按元件群分批 + 2 CRITICAL bug。⚠️ `AppMenuItem.vue` 那條必須先讀 source 再動（memory `feedback_appmenuitem_manual_verify`，側邊選單高亮敏感區）
- **BE Sonar 品質債**（Notion「[優化] BE Sonar 品質債 backlog」）：**只派安全桶**（未用變數 42 / 未用參數 83 / 註解碼 66 / 重複字面值 62）。⚠️ **禁區：S3776 認知複雜度 207 條（重構有語意風險）+ BLOCKER S3516 7 條（FR-038 stub 一族，盲修出事）**。且 BE 無測試安全網（§2.5），驗證只能靠 main_app 起得來 + 煙測
- **TipTap 編輯器收斂**（Notion「[優化] 富文本編輯器收斂到 TipTap」）：3 個 quill 表單換現成 `TipTapEditor.vue` → 拔 quill + ckeditor5。做完標「修正待驗證」等 user 手測，不自動關

**下一棒動作**：把各 case 補「🔧 Runner 動工指引」段（分批策略 / 禁區 / 驗證命令 / commit 規範）再派。
**小件未做**：FE `preact` 補升（direct dep、HIGH CVE-2026-22028、目標 10.28.2）——一行 + build 驗證，可順手做。

### §3.2 jedi-* 升版解殘留線（需 user 明示才動）

BE 殘留 6 條 CVE 中 4 條被 jedi-* 硬 pin 卡住：
| 套件 | 卡住來源 | 目標 |
|------|---------|------|
| flask 3.1.0 | jedi-common==0.0.27 pin Flask==3.1.0 | 3.1.3（LOW ×2） |
| marshmallow 3.23.2 | jedi-common pin | 3.26.2（MEDIUM，留 3.x） |
| python-dotenv 1.0.1 | jedi-oscal-v2==2.2.1 pin | 1.2.2（MEDIUM） |
| pytest 8.3.4 | jedi-oscal-v2 pin | 8.4+（MEDIUM，dev 工具） |

流程走 `jedi-package-dev` skill（path dependency dev → user 明示才發版推 Nexus）。另 2 條無解殘留：weasyprint CSS injection（上游 no-fix）+ flask 已含在上表。

### §3.3 CI/CD 線（等雷門環境準備）

Notion「[資安][基礎建設] 資安掃描進 GitLab CI」case 內含完整三層架構（gitleaks MR gate / trivy+semgrep 排程 / sonar）與雷門準備清單（runner 確認 / CI variables / SonarQube 搬家決策 / gate 嚴格度）。等 user 說準備好了再實作。

## §4 開工順位（下一棒依 user 指示擇一）

1. user 指定接哪條線 → 讀對應 §3.x → 開工
2. 若接 runner 線：先補 case 動工指引 → 等 user 確認 → 派工
3. 任何 BE 驗證：`main_app.py` + port 8000 + `/api/1.0/login` 空 body 回 400 = 正常

## §5 該讀的檔案

- Notion 任務清單（狀態真相源）：DB `23c346da-4cd0-8041-955e-000bb6976dd2`
- 掃描報告（**已 gitignore，勿 Read 整檔，jq 查詢**）：兩 repo `security-reports/`（本 session 結束時為修正後重掃版）
- BE 掃描腳本：`scripts/sonar_scan.sh`（SONAR_TOKEN 走環境變數；hotspots API 需 squ_ User Token，SONAR_USER_TOKEN 也在 ~/.zshrc）

## §6 Pre-flight（接手必跑）

```bash
cd ~/Projects/Billows/Audit-Manager/compliance-manager-be
git log --oneline -8   # 應見 9fb4a111 / 15d19e3a / 92145244 / 44aa0459 / f0a951eb / 88f33699 / 99ff37af
git status --short     # 應乾淨（untracked 不算）
cd ~/Projects/Billows/Audit-Manager/compliance-manager-fe
git log --oneline -6   # 應見 7e4030a / 3c5b411 / d404e3a / eb7fa8a / f3eca51 / c60dbde
git status --short
```

## §7 Verify 本 arc 確實 close

User 已手測驗收（2026-07-24 深夜）：FE dev server（vite 8）+ HMR + 頁面正常；BE main_app 起動 + 登入 + PDF 匯出。Notion 6 條修正 case 全標 Done。複驗可跑：
```bash
# 憑證歸零
cd ~/Projects/Billows/Audit-Manager/compliance-manager-be
for p in 7947959693 1366089469018767493 860100307; do grep -ral "$p" . --exclude-dir=.git --exclude-dir=security-reports --exclude-dir=log; done  # 應無輸出
# trivy 殘留（應 BE 6 條 / FE 35 條）
jq '[.Results[].Vulnerabilities // [] | .[] | .Severity] | group_by(.) | map({sev: .[0], count: length})' security-reports/trivy-backend.json
```

## §8 行為規範重要提醒

- 不切 branch / 顯式 git add 禁 -am / **push 永遠等 user 明示**（目前 13 commits 未 push）
- BE 起服務 = `main_app.py`（8000）；改 service code 必重啟（kill -9）
- jedi-* 異動需 user 明示；發版絕不自動推 Nexus
- 派 subagent 必帶大檔護欄（§2.2）+ 顯式 git add 警語
- user 說「先不用/等等」就停手，不搶跑

## §9 收尾流程

本 arc 主體已收（Notion Done ×7 含 xlsx/quill 討論條）。若後續線完成：對應 case 標「修正待驗證」→ user 驗 → Done。spec 更新不適用（資安修正非頁面行為變更；CORS/儲存設定行為若日後被問，代碼註解已足）。

## §10 不在本期 scope

- FE Dockerfile nginx USER（涉 port 映射，等部署決策）
- FE lockfile 不入版控問題（既有慣例，動它牽 CI，留給 CI case 一起考慮）
- BE pytest 環境修復（126 collection errors，值得開 case 但未開）
- git history rewrite 清歷史憑證（已 revoke，成本不值）

## §11 本 session commits（全部未 push）

**BE（7 commits）**：
```
9fb4a111 fix(security): BE 依賴安全升版——pillow 12.3/lxml 6.1/weasyprint 68/eventlet 0.40（Trivy 26 CVE 修復）
15d19e3a fix(security): Sonar 安全項——CORS 收斂 config 化、分類器 job 目錄脫離 /tmp、workflow mapper 死碼修正
92145244 fix(security): 程式碼硬化——報告 XSS sanitize、BPMN 解析改 defusedxml、上傳檔名 secure_filename、classify Dockerfile 非 root
44aa0459 chore(gitignore): 排除 security-reports/
f0a951eb chore(gitignore): 排除 .scannerwork/
88f33699 fix(security): 憑證清理補漏 1 檔（超長行 grep 靜默漏掉那檔）
99ff37af fix(security): 憑證清理主體（.env.sample/.env.test + conversation-history 14 檔）
```
**FE（6 commits）**：
```
7e4030a fix(security): 移除未使用的 xlsx 依賴
3c5b411 fix(security): 依賴安全升版——axios/dompurify/vite 等
d404e3a chore(gitignore): 排除 security-reports/
eb7fa8a chore(gitignore): 排除 .scannerwork/
f3eca51 fix(security): sonar-project.properties 移除明文 admin 帳密
c60dbde fix(security): camunda-api 移除硬編內網位址、儲存設定 local 路徑預設脫離 /tmp
```
部署注意：classify docker image 需各主機 rebuild（Dockerfile 加了 USER）；分類器 job 目錄換位置，部署環境 `-v` 掛載路徑需同步。

## §12 給 fresh session 的超短 prompt

```
請讀 docs/features/security-scan-2607/handoff/2026-07-24-security-scan-arc-session-handoff.md，
先答出 §0 冷接自檢 4 問（不要跳過 WHY），再跑 §6 pre-flight。
本 arc 主體已完成驗收，你的工作是接剩餘線（§3）：等我指定接哪條再動工。
注意：BE 起服務用 main_app.py（port 8000）；所有 commits 未 push，push 等我明示。
```
