網站維運

CSP 怎麼設才嚴格又不把網站弄壞:從盤點、上線到驗證

嚴格 CSP 應以最小來源、雜湊或 nonce、禁止行內事件與框架嵌入為核心,先用 Report-Only 盤點,再以自動化測試維持政策與程式同步。

CSP 怎麼設才嚴格又不把網站弄壞:從盤點、上線到驗證

嚴格 CSP 應以最小來源、雜湊或 nonce、禁止行內事件與框架嵌入為核心,先用 Report-Only 盤點,再以自動化測試維持政策與程式同步。

01

CSP 管的是瀏覽器可以載入與執行什麼

Content Security Policy 是由伺服器回傳的瀏覽器政策。它能限制腳本、樣式、圖片、連線、框架、表單目的地與基底網址等來源,降低 XSS、內容注入與第三方資源被替換後的影響。

CSP 不是輸入驗證或輸出編碼的替代品。它最適合當第二道防線:即使程式某處漏掉編碼,瀏覽器仍不應任意執行攻擊者插入的腳本。

02

先盤點,不要從萬用白名單開始

列出每一種資源的實際來源:外部 JavaScript、CSS、字型、圖片、API、WebSocket、frame、Service Worker 與表單。能改成本機託管就減少外部依賴;不需要的類型直接設為 'none'

default-src 'none' 為基礎逐項開放通常最清楚。若既有大型網站難以一步到位,可先用 Content-Security-Policy-Report-Only 收集違規,但報告端點本身也要做流量限制與資料最小化。

03

腳本策略是核心

不要用 'unsafe-inline' 解決行內腳本錯誤,也避免過寬的 https:*。靜態網站可將固定行內 JSON-LD 或必要程式計算 SHA-256 雜湊;動態網站可為每次回應產生不可預測的 nonce。外部腳本最好由同源提供並使用版本化檔名。

同時設定 script-src-attr 'none',移除 onclick 等行內事件。若採 Trusted Types,先確認程式不依賴危險 HTML sink,再強制 require-trusted-types-for 'script'

04

容易忽略的邊界

  • base-uri 'none' 防止注入 base 標籤改寫相對連結。
  • object-src 'none'frame-src 'none' 關閉不需要的外掛與內嵌頁面。
  • frame-ancestors 'none' 防止網站被其他頁面嵌入。
  • form-action 'none' 適合沒有表單送出的純靜態網站。
  • worker-src 'self' 僅在確實使用 Service Worker 時開放。

圖片若只來自本站與固定圖片網域,就不要保留 data: 或任意 HTTPS。每多一個來源,都要能說明用途與負責人。

05

從 Report-Only 走到正式阻擋

先在測試環境跑完整瀏覽路徑,再於正式環境短期使用 Report-Only。分類報告時排除瀏覽器擴充功能與無法控制的雜訊,針對真實缺口修正程式或精確開放來源,不要直接加入萬用規則。

正式啟用後保留回復方式,並同步監控頁面錯誤率、主要轉換流程與 CSP 違規。政策變更應與程式版本一起審查,避免部署新行內腳本卻忘了更新雜湊。

06

每次發布都自動驗證

在建置流程中解析所有 HTML,列出無 src 的 script,重算雜湊並與 CSP 比對;任何未覆蓋或已失效的雜湊都應使驗證失敗。另檢查是否出現 unsafe-inline、萬用來源、HTTP 資源與未預期網域。

瀏覽器端再以乾淨設定檔測試桌機、行動裝置、離線頁與錯誤頁。好的 CSP 不只是「首頁沒有紅字」,而是所有公開路徑都遵守相同的來源邊界。