本文將說明如何透過最近推出的「Issues」分頁,實作 DevTools 支援功能,以便偵錯內容安全政策 (CSP) 問題。
實作工作是在 2 次實習期間完成:在第一階段,我們建立了一般報表架構,並設計了 3 個 CSP 違規問題的問題訊息。2. 在第二次測試期間,我們新增了信任類型問題,以及一些專門用於信任類型偵錯的 DevTools 功能。
什麼是內容安全政策?
內容安全政策 (CSP) 可限制網站中的特定行為,以提升安全性。舉例來說,CSP 可用於禁止內嵌指令碼或 eval
,這兩者都能減少跨網站指令碼 (XSS) 攻擊的攻擊面。如需 CSP 的詳細說明,請參閱這裡。
Trusted Types(TT) 政策是一種特別的新 CSP,可啟用動態分析,有系統地防範網站上的大量插入攻擊。為達成這項目標,TT 支援網站監控其 JavaScript 程式碼,只允許將特定類型的項目指派給 DOM 接收器,例如 innerHTML。
網站可以透過加入特定的 HTTP 標頭,啟用內容安全政策。舉例來說,標頭 content-security-policy: require-trusted-types-for 'script'; trusted-types default
會為網頁啟用 TT 政策。
每項政策可採用下列其中一種模式運作:
- 強制模式:每項政策違規都會產生錯誤
- 僅回報模式:將錯誤訊息回報為警告,但不會導致網頁失敗。
在「Issues」分頁中實作內容安全政策問題
這項工作的目標是改善 CSP 問題的偵錯體驗。在考慮新問題時,開發人員工具團隊大致會遵循以下程序:
- 定義使用者案例。找出開發人員工具前端中的使用者故事,其中說明網頁程式開發人員如何調查問題。
- 前端實作。根據使用者故事,找出前端調查問題時需要哪些資訊 (例如相關要求、Cookie 名稱、指令碼或 HTML 檔案中的一行)。
- 問題偵測。找出瀏覽器中在 Chrome 中偵測到問題的位置,然後指示回報問題的位置,並附上步驟 (2) 的相關資訊。
- 儲存並顯示問題。將問題儲存在適當位置,並在開發人員工具開啟時提供這些問題
- 設計問題文字。提供說明文字,協助網頁開發人員瞭解並解決問題
步驟 1:定義 CSP 問題的使用者故事
開始實作程序前,我們先建立一份含有使用者故事的設計文件,以進一步瞭解需要採取的行動。舉例來說,我們編寫了以下使用者故事:
身為開發人員,我剛發現網站的某些部分遭到封鎖,因此想:- - ...找出 CSP 是否是導致網站上 iframe / 圖片遭到封鎖的原因 - ...瞭解哪個 CSP 指示會導致特定資源遭到封鎖 - ...瞭解如何變更網站的 CSP,以便顯示目前遭到封鎖的資源 / 執行目前遭到封鎖的 js。
為了探索這個使用者情境,我們建立了一些簡單的範例網頁,展示我們感興趣的 CSP 違規情形,並探索範例網頁,讓自己熟悉這個程序。以下是一些網頁範例 (開啟示範專案,並開啟「Issues」分頁):
我們透過這個程序,瞭解來源位置是偵錯 CSP 問題時最重要的資訊。我們也發現,在資源遭到封鎖的情況下,快速找出相關聯的 iframe 和要求也很有幫助,此外,在 DevTools 的「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 產生 DevTools 前端所需的 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++ 程式庫,這個程式庫會從 C++ Chromium 後端對開發人員工具的後端產生及傳送這些資料結構。使用該程式庫,您可以使用下列 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:儲存並顯示問題
我們也想回報開發人員工具尚未開啟前發生的問題,這點與控制台訊息的處理方式類似,也就是說,我們不會立即將問題回報至前端,而是使用儲存空間,在開發人員工具開啟或關閉時,都會填入問題。只要開啟 DevTools (或連結任何其他 CDP 用戶端),即可從儲存空間重播先前記錄的所有問題。
後端工作已完成,接下來需要專注在前端的問題呈現方式。
步驟 5:設計問題文字
舉例來說,設計問題文字是一種流程,牽涉到多個團隊。舉例來說,我們經常仰賴實作某項功能的團隊 (在這個案例中為 CSP 團隊) 和 DevRel 團隊,決定網頁開發人員應如何處理特定類型的問題。問題文字通常會經過一些精進,直到完成為止。
通常,DevTools 團隊會先根據他們的構想草擬草稿:
## 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/
經過疊代後,我們得到以下結果:
如您所見,邀請功能團隊和 DevRel 團隊參與,可讓說明更清楚明確!
您也可以在專門用於 CSP 違規事項的分頁中,查看網頁上的 CSP 問題。
偵錯 Trusted Types 問題
如果沒有合適的開發人員工具,大規模使用 TT 可能會相當困難。
改善主控台列印功能
使用可信賴的物件時,我們至少會顯示與不受信任的物件相同數量的資訊。很抱歉,目前在顯示信任物件時,系統不會顯示包裝物件的相關資訊。
這是因為控制台中顯示的值,預設會從對物件呼叫 .valueOf()
取得。不過,在信任類型中,傳回的值並不實用。我們希望您在呼叫 .toString()
時看到的內容。為達成這項目標,我們需要修改 V8 和 Blink,以便為信任類型物件引進特殊處理機制。
雖然基於歷史因素,這項自訂處理作業是在 V8 中進行,但這種方法仍有重大的缺點。許多物件都需要自訂顯示,但在 JS 層級的類型相同。由於 V8 是純 JS,因此無法區分與 Web API 相對應的概念,例如信任類型。因此,V8 必須請其嵌入者 (Blink) 協助區分這兩者。
因此,將該部分程式碼移至 Blink 或任何內嵌程式似乎是合理的選擇。除了公開的問題之外,還有許多其他好處:
- 每個嵌入器都可以產生自己的說明
- 透過 Blink API 產生說明會更簡單
- Blink 可存取物件的原始定義。因此,如果我們使用
.toString()
產生說明,.toString()
就不會重新定義。
違規中斷 (在「僅報表」模式中)
目前偵錯 TT 違規的唯一方法,就是在 JS 例外狀況上設定中斷點。由於強制執行的 TT 違規會觸發例外狀況,這項功能或許會有所幫助。不過,在實際情況中,您需要對違反條款的情況進行更精細的控管。特別是,我們希望只在發生 TT 違規 (而非其他例外狀況) 時中斷,並在僅報模式下中斷,以及區分不同類型的 TT 違規。
開發人員工具箱已支援多種中斷點,因此架構可擴充性相當高。如要新增中斷點類型,您必須在後端 (Blink)、CDP 和前端進行變更。我們應該引入新的 CDP 指令,讓我們稱之為 setBreakOnTTViolation
。前端會使用這個指令,告知後端應違反何種 TT 違規行為。後端 (特別是 InspectorDOMDebuggerAgent
) 會提供「探針」onTTViolation()
,每次發生 TT 違規時都會呼叫。接著,InspectorDOMDebuggerAgent
會檢查該違規事項是否應觸發中斷點,如果是,就會傳送訊息至前端,以便暫停執行作業。
目前進度和後續步驟
自從這裡說明的問題出現以來,「Issues」分頁已進行許多變更:
- 與 DevTools 中其他面板的連結性已改善。
- 我們已將許多其他問題的回報功能移至「Issues」分頁,包括低對比、信任的網頁活動、奇異模式、歸因回報 API 和CORS 相關問題等。
- 推出隱藏問題功能
日後,我們打算使用「問題」分頁顯示更多問題,這樣長遠來說,就能從控制台移除無法讀取的錯誤訊息流程。
下載預覽頻道
建議您將 Chrome Canary、開發人員版或Beta 版設為預設開發人員版瀏覽器。這些預覽管道可讓您存取最新的 DevTools 功能,測試最新的網路平台 API,並在使用者發現問題前,協助您找出網站的問題!
與 Chrome 開發人員工具團隊聯絡
請使用下列選項討論新功能、更新或任何與開發人員工具相關的內容。
- 請透過 crbug.com 提交意見回饋和功能要求。
- 在開發人員工具中,依序點選 和 [更多選項] > [說明] > [回報開發人員工具問題] 回報開發人員工具問題。
- 在 Twitter 上傳送訊息給 @ChromeDevTools。
- 在 YouTube 影片「What's new in DevTools」或「DevTools 提示」YouTube 影片中留言。