2026 年遠端 Mac 前端避坑:
CSP nonce、strict-dynamic 與 Safari 報錯對照表——發布前三步驗收
適用對象:上線 CSP、以 nonce/hash 取代 unsafe-inline,卻遇 Safari 單獨異常 的 Web 團隊。含:CSP 與 WebKit 差異、nonce/hash 表、strict-dynamic 步驟、遠端 Safari 流程、FAQ、可貼 Header 與三步驗收。延伸 部署與 Safari 驗證、Playwright WebKit。💻🚀
01 CSP 基礎與 Safari 差異
拿掉 script-src 的 'unsafe-inline' 後,行內腳本須靠 nonce 或 SHA-256 hash。WebKit 對行內處理常式、javascript:、部分 Worker 與第三方注入常比 Chromium 更嚴;僅驗 Chrome 不足以代表 Safari 使用者。
- 動態注入:標籤管理與延遲 bundle 須繼承 nonce 或以 hash 鎖定短啟動片段。
- iframe:
frame-src過緊會讓金流/OAuth 靜默失敗。 - HTML 快取:舊 nonce 的快取頁會間歇拒絕腳本;快取鍵須含 nonce 或不快取 shell。
style-src 行內同樣要 nonce/hash;第三方動態寫樣式須列例外。可引用:① hydration 與 chunk 鏈都要納入政策 ② 報表端點預發布須與正式一致 ③ 私密視窗減少擴充套件干擾。
02 nonce/hash 設定對照表
SSR/邊緣 HTML 用每請求 nonce;位元組固定的短行內片段可用 hash。
| 項目 | Nonce | SHA-256 hash |
|---|---|---|
| 標頭寫法 | script-src 'nonce-值' … 與標籤 nonce 一致。 |
'sha256-Base64',行內位元組須完全一致。 |
| 適用情境 | SSR、每請求 HTML、strict-dynamic 鏈。 | 固定啟動腳本、小 JSON-LD。 |
| 維運風險 | 快取未分鍵、nonce 未旋轉。 | 格式化變更即失效。 |
| Safari 注意 | chunk/hydration 皆須繼承 shell 的 nonce。 | minify 差異即拒絕。 |
每請求產生 res.locals.cspNonce,再設定:
const n = res.locals.cspNonce;
res.setHeader('Content-Security-Policy', [
`default-src 'self'`,
`script-src 'nonce-${n}' 'strict-dynamic' https:`,
`style-src 'self' 'nonce-${n}'`,
`object-src 'none'`,
`base-uri 'none'`,
`frame-ancestors 'none'`
].join('; '));
鏈穩定後可收斂 https: 等寬鬆項。Web Inspector FAQ。
03 strict-dynamic 落地步驟
'strict-dynamic':nonce 腳本可信任其子載入;單靠主機列通常無法放行未帶 nonce 的動態插入腳本。
- 根腳本:首個同步
<script>帶 nonce 並啟動依賴圖。 - 懶載入:僅由已信任程式觸發;裸第三方
script須改寫或加 nonce。 - 收斂 URL 列:鏈穩後縮
script-src,connect-src對齊真實 API。 - Report-Only:先複製正式 nonce 策略收集誤報再 enforce。
- Worker:SW/worker 路徑須符合靜態或同等信任規則。
04 遠端 Safari/WebKit 驗證流程
遠端 Mac提供真實 Safari 組建:HTTPS 開預發布、開發選單+Web Inspector,勝過僅跑 Linux 上 Blink。
- 私密視窗減少擴充套件雜訊。
- 主控台+網路對照
blocked:csp。 - Playwright webkit可冒煙;金流/OAuth 宜手測。
| Safari 主控台訊息(要旨) | 可能指令 | 處理方向 |
|---|---|---|
| 拒絕執行…缺少 hash、nonce 或 unsafe-inline | script-src |
對齊 nonce;清 HTML 快取。 |
| 拒絕載入…違反 CSP | connect-src/frame-src |
補 API;放行 iframe 來源。 |
| 行內樣式違反 CSP | style-src |
外部 CSS、hash 或 style nonce。 |
05 常見攔截 FAQ
- Chrome OK、Safari 壞?預設 WebKit 更嚴,真機簽核。
- strict-dynamic?動態鏈靠 nonce,勿迷信長 URL 白名單。
- 共用 nonce?每回應唯一;勿長快取含 nonce 的 HTML。
06 發布前三步驗收清單
① 預發布 CSP 與正式一致,關鍵路徑主控台乾淨。② 每則 blocked:csp 對到指令並修復或記錄例外。③ 釋出單附 Safari/OS 版本與截圖/HAR。strict-dynamic 下首個受信腳本即邊界;第三方 SDK 納入鏈或 hash。
- 步驟一:報告端點亦須與正式一致。
- 步驟二:登入、結帳、儀表板、錯誤頁無未解 CSP 拒絕。
- 步驟三:版本與附件進工單供迴歸。