在 Chrome 開發人員工具中實作 CSP 和 Trusted Types 偵錯功能

Kateryna Prokopenko
Kateryna Prokopenko
Alfonso Castaño
Alfonso Castaño

這篇網誌文章說明如何導入開發人員工具,以協助最近推出的「問題」分頁對內容安全政策 (CSP) 問題進行偵錯。

實作工作是在 2 名實習機會中完成: 1. 第一種是針對 3 個 CSP 違規問題建構了一般回報架構,並設計了問題訊息。2. 在第二階段中,我們加入了可信任類型問題,以及一些用於信任類型的偵錯專用開發人員工具功能。

什麼是內容安全政策?

內容安全政策 (CSP) 可讓您限制網站的特定行為,藉此提升安全性。舉例來說,CSP 可以用來禁止內嵌指令碼,或是禁止 eval,這兩者都能減少跨網站指令碼 (XSS) 攻擊的攻擊途徑。如需 CSP 的詳細簡介,請參閱這篇文章

全新的 CSP 是 Trusted Types(TT) 政策,該政策可啟用動態分析,有系統地防止網站上大量的植入式攻擊。為了達到這個目標,TT 支援用來控制 JavaScript 程式碼的網站,只允許特定類型的內容被指派到 DOM 接收器,例如 innerHTML。

網站可以加入特定的 HTTP 標頭,藉此啟用內容安全政策。舉例來說,content-security-policy: require-trusted-types-for 'script'; trusted-types default 標頭會啟用網頁的 TT 政策。

每項政策皆可在下列任一模式下運作:

  • 強制執行模式:每個政策違規事項都錯誤。
  • 報表專用模式:將錯誤訊息回報為警告,但不會導致網頁發生錯誤。

在「問題」分頁中實作內容安全政策問題

這項工作的目標是改善 CSP 問題的偵錯體驗。考慮新問題時,開發人員工具團隊大致遵循以下流程:

  1. 定義使用者故事。在開發人員工具前端找出一組使用者故事,其中說明網頁程式開發人員如何調查問題。
  2. 前端實作。根據使用者案例,從前端找出調查問題所需的資訊 (例如相關要求、Cookie 名稱、指令碼或 HTML 檔案中的行或 HTML 檔案等)。
  3. 問題偵測:請找出瀏覽器中在 Chrome 中偵測到問題的位置,並調整工具以回報問題,包括步驟 (2) 中的相關資訊。
  4. 儲存並顯示問題。將問題儲存在適當位置,開啟後供開發人員工具使用
  5. 設計問題文字。撰寫說明文字,協助網頁程式開發人員瞭解,更重要的是修正問題

步驟 1:定義 CSP 問題的使用者故事

在開始導入作業前,我們製作了一份設計文件,其中包含使用者故事,進一步瞭解我們需要採取的行動。例如,我們寫下以下使用者案例:


身為開發人員,他才知道網站的特定部分遭到封鎖,因此想:- - ...瞭解 CSP 是造成網站上 iframe / 圖片遭到封鎖的原因 - ...瞭解哪些 CSP 指令導致特定資源遭到封鎖 - ...瞭解如何變更網站的 CSP,允許顯示目前遭封鎖的資源 / 執行目前遭封鎖的資源。


為探討這個使用者故事,我們製作了幾個簡單的範例網頁,列出我們感興趣的 CSP 違規事項,並瀏覽示例網頁來熟悉相關流程。 以下提供部分網頁範例 (開啟示範模式,並在「問題」分頁中開啟):

透過這個程序,我們得知來源位置是 CSP 問題偵錯時最重要的資訊。此外,如果資源遭到封鎖,您還能快速找到相關聯的 iframe 和要求,而開發人員工具的「Elements」面板中的 HTML 元素直接連結也非常實用。

步驟 2:前端實作

我們希望透過 Chrome 開發人員工具通訊協定 (CDP) 提供給開發人員工具,並將這些資訊轉換為第一份草稿,並將這項深入分析結果轉化為第一份草稿:

以下摘錄自 third_party/blink/public/devtools_protocol/browser_protocol.pdl

 type ContentSecurityPolicyIssueDetails extends object
   properties
     # The url not included in allowed sources.
     optional string blockedURL
     # Specific directive that is violated, causing the CSP issue.
     string violatedDirective
     boolean isReportOnly
     ContentSecurityPolicyViolationType contentSecurityPolicyViolationType
     optional AffectedFrame frameAncestor
     optional SourceCodeLocation sourceCodeLocation
     optional DOM.BackendNodeId violatingNodeId

上述定義基本上是對 JSON 資料結構進行編碼。是以簡易語言編寫,稱為 PDL (通訊協定資料語言)。PDL 用於兩種用途首先,我們使用 PDL 產生開發人員工具前端依賴的 TypeScript 定義。舉例來說,上述的 PDL 定義會產生下列 TypeScript 介面:

export interface ContentSecurityPolicyIssueDetails {
  /**
  * The url not included in allowed sources.
  */
  blockedURL?: string;
  /**
  * Specific directive that is violated, causing the CSP issue.
  */
  violatedDirective: string;
  isReportOnly: boolean;
  contentSecurityPolicyViolationType: ContentSecurityPolicyViolationType;
  frameAncestor?: AffectedFrame;
  sourceCodeLocation?: SourceCodeLocation;
  violatingNodeId?: DOM.BackendNodeId;
}

其次,更重要的是,我們會根據 C++ Chromium 後端產生及將這些資料結構從 C++ Chromium 後端傳送至 DevTools 前端的定義產生 C++ 程式庫。您可以使用這個程式庫,使用下列 C++ 程式碼建立 ContentSecurityPolicyIssueDetails 物件:

protocol::Audits::ContentSecurityPolicyIssueDetails::create()
  .setViolatedDirective(d->violated_directive)
  .setIsReportOnly(d->is_report_only)
  .setContentSecurityPolicyViolationType(BuildViolationType(
      d->content_security_policy_violation_type)))
  .build();

決定要提供哪些資訊後,我們就必須探索 Chromium 中該從何處取得這類資訊。

步驟 3:偵測問題

為了以上一節所述格式向 Chrome 開發人員工具通訊協定 (CDP) 提供資訊,我們需要在後端找出資訊實際可用的位置。幸運的是,CSP 程式碼已有一個瓶頸,用於報表專用模式,可能遇到以下情況:ContentSecurityPolicy::ReportViolation 向 (選用) 報表端點回報問題 (可在 CSP HTTP 標頭中設定)。我們需要回報的大部分資訊都已就緒,因此檢測作業在後端不需要大幅變更。

步驟 4:儲存並顯示問題

其中較不複雜,因為我們還想回報在開發人員工具開啟前發生的問題,與控制台訊息的處理方式類似。也就是說,我們不會直接向前端回報問題,而是使用充滿問題的儲存空間,不論開發人員工具是否開啟。開啟開發人員工具後 (如果是附加任何其他 CDP 用戶端),可在儲存空間中重播先前記錄的所有問題。

這已做到後端工作,我們現在必須把重點放在如何從前端找出問題。

步驟 5:設計問題文字

設計問題文字是一個程序,除了我們自己以外,還涉及數個團隊。舉例來說,我們通常會仰賴導入某項功能的團隊 (在本例中為 CSP 團隊) 以及 DevRel 團隊,該團隊設計了網頁程式開發人員應如何處理特定類型的問題。問題文字通常會經過一些修正,直到完成為止。

一般來說,開發人員工具團隊會先說明他們想像的粗略草稿:


## Header
Content Security Policy: include all sources of your resources in content security policy header to improve the functioning of your site

## General information
Even though some sources are included in the content security policy header, some resources accessed by your site like images, stylesheets or scripts originate from sources not included in content security policy directives.

Usage of content from not included sources is restricted to strengthen the security of your entire site.

## Specific information

### VIOLATED DIRECTIVES
`img-src 'self'`

### BLOCKED URLs
https://imgur.com/JuXCo1p.jpg

## Specific information
https://web.dev/strict-csp/

經過疊代後,我們將抵達:

ALT_TEXT_HERE

如您所見,與功能團隊和 DevRel 一同讓說明更加清楚明確!

您也可以透過專門說明 CSP 違規事項的分頁,查看網頁上的 CSP 問題。

對信任類型問題進行偵錯

如果沒有合適的開發人員工具,就能大規模處理 TT 作業。

改善控制台列印功能

在使用「可信物件」時,我們會希望與不受信任物件顯示的資訊數量至少相同。很遺憾,目前顯示受信任的物件時,系統不會顯示任何包裝物件的相關資訊。

這是因為根據預設,控制台中顯示的值是從物件的 .valueOf() 呼叫取得。但就「Trusted Type」而言,傳回的值並不實用。而是希望取得類似於呼叫 .toString() 時得到的內容。為此,我們需要修改 V8 和 Blink,為受信任型別物件導入特殊處理方式。

雖然基於歷史因素,這項自訂處理方式是在 V8 中完成,但這種方法具有重大缺點。許多物件需要自訂顯示,但類型與 JS 層級相同。由於 V8 是純 JS,因此無法區分與 Web API 對應的概念,例如「Trusted Type」。因此,V8 必須要求其嵌入工具 (Blink) 來協助區別。

因此,將這個部分程式碼移到 Blink 或任何嵌入式程式聽起來都很有理性。除了暴露的問題外,還有許多其他好處:

  • 每個嵌入程式都能產生專屬的說明產生項目
  • 透過 Blink API 產生說明較為輕鬆
  • Blink 可以存取物件的原始定義。因此,如果使用 .toString() 產生說明,就不太可能重新定義 .toString()

違規入侵 (僅限報表模式)

目前對 TT 違規進行偵錯的唯一方法,就是在 JS 例外狀況中設定中斷點。由於強制執行的 TT 違規會觸發例外狀況,因此這項功能在許多方面很實用。不過在現實生活中,您需要更精細地控管 TT 違規行為。具體來說,我們只希望在發生 TT 違規時 (而非其他例外狀況) 進行處置,同時進入「僅限報表」模式,並區分不同類型的 TT 違規行為。

開發人員工具已支援各種中斷點,因此架構十分可擴充。新增中斷點類型時,必須在後端 (Blink)、CDP 和前端進行變更。我們應導入新的 CDP 指令,將其命名為 setBreakOnTTViolation。前端會使用這個指令向後端指出應損毀的 TT 違規類型。後端,特別是 InspectorDOMDebuggerAgent 會提供「探測器」onTTViolation(),每當發生 TT 違規時就會呼叫。接著,InspectorDOMDebuggerAgent 會確認違規是否應觸發中斷點,如果發生這種情況,則傳送訊息至前端以暫停執行。

完成內容和後續步驟

自從我們在這裡導入了一些問題以來,「問題」分頁做了許多調整:

我們計劃從往後使用「Issues」分頁來顯示更多問題,進而在長時間執行期間卸載控制台,無法載入無法閱讀的錯誤訊息。

下載預覽管道

考慮使用 Chrome Canary 版開發人員版Beta 版做為預設開發瀏覽器。這些預覽管道可讓您存取開發人員工具的最新功能、測試最先進的網路平台 API,並在使用者使用之前就在網站上發現問題!

與 Chrome 開發人員工具團隊聯絡

使用下列選項,討論文章的新功能和異動,以及其他與開發人員工具相關的事項。

  • 請透過 crbug.com 提交建議或意見回饋。
  • 如要回報開發人員工具的問題,請在開發人員工具中依序點選「更多選項」圖示 更多   >「說明」 >「回報開發人員工具的問題」
  • @ChromeDevTools 張貼推文。
  • 歡迎對開發人員工具的 YouTube 影片或開發人員工具秘訣 (YouTube 影片) 提供意見。