跳轉到

D-20260812-04|CSP 逐頁雜湊與不安全請求升級

背景與驅動力

Angular prerender 會在不同路由產生不同 inline import map、JSON-LD 與非阻塞 stylesheet handler; 單一靜態 CSP 無法在不放寬 unsafe-inline 的前提下涵蓋所有頁面。現行 generator 已採逐頁 hash, 但 canon 仍描述靜態常數,且 generator 漏掉原決策列入的 upgrade-insecure-requests

考慮過的選項

  • 全頁共用 script-src 'unsafe-inline':簡單但失去 inline script 注入防線,棄。
  • 移除 upgrade-insecure-requests 以支援 localhost:Chromium 實測 localhost 本就保留 HTTP,前提 不成立,且會讓正式站失去未來誤植 HTTP resource 時的縱深防禦,棄。
  • 逐頁精確 SHA-256,加上固定安全 baseline 與 upgrade-insecure-requests(採納)。

決定

  • production prerender 後遍歷每份 HTML,逐頁計算所有無 src inline script 的 SHA-256; script-src 固定含 'self''wasm-unsafe-eval',永不加入 'unsafe-inline'
  • 只有頁面含 inline event handler 時,才加入 'unsafe-hashes' 與各 handler 的 SHA-256。
  • 固定 baseline 含 upgrade-insecure-requests;localhost 煙測保留,且不以移除 production 安全 directive 作為本機開發相容手段。
  • connect-src 'self' wss: https: 與 meta CSP 無 frame-ancestors 的既有決策不變。

後果與影響

每份 prerender HTML 只允許自身實際內嵌內容,新增或變更 inline 內容會自然得到新 hash,而不是 要求人工同步全站常數。正式站同時恢復 insecure subresource 升級保護。代價是 CSP 只能在 build 產物生成後確定,注入器與其測試因此成為 production build 的必要安全閘。

本決策修訂 D-20260703-01 的「靜態 CSP_META」實作描述; build 時 meta 交付、scheme 級 connect-src 與 clickjacking 風險接受仍然有效。