Bài đăng trên blog này nói về việc triển khai tính năng hỗ trợ của DevTools để gỡ lỗi các vấn đề về Chính sách bảo mật nội dung (CSP) bằng thẻ Vấn đề mới ra mắt gần đây.
Công việc triển khai được thực hiện trong 2 kỳ thực tập: 1. Trong giai đoạn đầu tiên, chúng tôi đã xây dựng khung báo cáo chung và thiết kế thông báo về vấn đề cho 3 vấn đề vi phạm CSP. 2. Trong phần thứ hai, chúng tôi đã thêm các vấn đề về Trusted Type cùng với một số tính năng DevTools chuyên biệt để gỡ lỗi Trusted Type.
Chính sách bảo mật nội dung là gì?
Chính sách bảo mật nội dung (CSP) cho phép hạn chế một số hành vi nhất định trên trang web để tăng cường bảo mật. Ví dụ: bạn có thể sử dụng CSP để không cho phép tập lệnh cùng dòng hoặc không cho phép eval. Cả hai cách này đều giúp giảm bề mặt tấn công cho các cuộc tấn công Tạo tập lệnh trên nhiều trang web (XSS). Để xem nội dung giới thiệu chi tiết về CSP, hãy đọc tại đây.
Một CSP đặc biệt mới là chính sách Trusted Types(TT), cho phép phân tích động có thể ngăn chặn một cách có hệ thống một loại tấn công tiêm mã lớn trên các trang web. Để đạt được điều này, TT hỗ trợ một trang web trong việc kiểm soát mã JavaScript của trang web đó để chỉ cho phép một số loại nội dung nhất định được gán cho các bồn lưu trữ DOM như innerHTML.
Trang web có thể kích hoạt chính sách bảo mật nội dung bằng cách thêm một tiêu đề HTTP cụ thể. Ví dụ: tiêu đề content-security-policy: require-trusted-types-for 'script'; trusted-types default kích hoạt chính sách TT cho một trang.
Mỗi chính sách có thể hoạt động ở một trong các chế độ sau:
- chế độ thực thi – mọi lỗi vi phạm chính sách đều là lỗi,
- chế độ chỉ báo cáo – báo cáo thông báo lỗi dưới dạng cảnh báo nhưng không gây ra lỗi trên trang web.
Triển khai các vấn đề về Chính sách bảo mật nội dung trong thẻ Vấn đề
Mục tiêu của công việc này là cải thiện trải nghiệm gỡ lỗi cho các vấn đề về CSP. Khi xem xét các vấn đề mới, nhóm DevTools thường tuân theo quy trình sau:
- Xác định câu chuyện người dùng. Xác định một tập hợp các câu chuyện người dùng trong giao diện người dùng của Công cụ cho nhà phát triển, bao gồm cả cách nhà phát triển web cần điều tra vấn đề.
- Triển khai giao diện người dùng. Dựa trên câu chuyện người dùng, hãy xác định những thông tin cần thiết để điều tra vấn đề ở giao diện người dùng (ví dụ: yêu cầu liên quan, tên cookie, một dòng trong tập lệnh hoặc tệp html, v.v.).
- Phát hiện vấn đề. Xác định những vị trí trong trình duyệt mà vấn đề có thể được phát hiện trong Chrome và trang bị cho vị trí đó để báo cáo vấn đề, bao gồm cả thông tin liên quan từ bước (2).
- Lưu và hiển thị các vấn đề. Lưu trữ các vấn đề ở một nơi thích hợp và cung cấp các vấn đề đó cho Công cụ cho nhà phát triển sau khi mở
- Thiết kế văn bản về vấn đề. Đưa ra một văn bản giải thích giúp nhà phát triển web hiểu và quan trọng hơn là khắc phục vấn đề
Bước 1: Xác định câu chuyện người dùng cho các vấn đề về CSP
Trước khi bắt đầu triển khai, chúng tôi đã tạo một tài liệu thiết kế kèm theo câu chuyện người dùng để hiểu rõ hơn những việc cần làm. Ví dụ: chúng tôi đã viết ra câu chuyện người dùng sau:
Là một nhà phát triển vừa nhận ra rằng một số phần trên trang web của mình bị chặn, tôi muốn:- - ...tìm hiểu xem CSP có phải là lý do khiến iframe / hình ảnh bị chặn trên trang web của tôi hay không - ...tìm hiểu xem chỉ thị CSP nào khiến một tài nguyên nhất định bị chặn - ...biết cách thay đổi CSP của trang web để cho phép hiển thị các tài nguyên hiện đang bị chặn / thực thi js hiện đang bị chặn.
Để khám phá câu chuyện người dùng này, chúng tôi đã tạo một số trang web mẫu đơn giản cho thấy các lỗi vi phạm CSP mà chúng tôi quan tâm, đồng thời khám phá các trang mẫu để tự làm quen với quy trình này. Dưới đây là một số trang web mẫu (mở bản minh hoạ khi thẻ Vấn đề đang mở):
Thông qua quy trình này, chúng tôi nhận thấy rằng vị trí nguồn là thông tin quan trọng nhất để gỡ lỗi các vấn đề về CSP. Chúng tôi cũng nhận thấy việc nhanh chóng tìm thấy iframe và yêu cầu liên quan trong trường hợp tài nguyên bị chặn là rất hữu ích, đồng thời đường liên kết trực tiếp đến phần tử HTML trong bảng điều khiển Elements (Phần tử) của Công cụ cho nhà phát triển cũng có thể hữu ích.
Bước 2: Triển khai giao diện người dùng
Chúng tôi đã biến thông tin chi tiết này thành bản nháp đầu tiên của thông tin mà chúng tôi muốn cung cấp cho Công cụ cho nhà phát triển thông qua Giao thức Chrome DevTools (CDP):
Dưới đây là đoạn trích từ 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
Về cơ bản, định nghĩa trên mã hoá cấu trúc dữ liệu JSON. Nó được viết bằng một ngôn ngữ đơn giản gọi là PDL (ngôn ngữ dữ liệu giao thức). PDL được dùng cho hai mục đích. Trước tiên, chúng tôi sử dụng PDL để tạo các định nghĩa TypeScript mà giao diện người dùng Công cụ cho nhà phát triển dựa vào. Ví dụ: định nghĩa PDL ở trên tạo ra giao diện TypeScript sau:
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;
}
Thứ hai, và có lẽ quan trọng hơn, chúng tôi tạo một thư viện C++ từ định nghĩa xử lý việc tạo và gửi các cấu trúc dữ liệu này từ phần phụ trợ C++ Chromium đến giao diện người dùng DevTools. Khi sử dụng thư viện đó, bạn có thể tạo đối tượng ContentSecurityPolicyIssueDetails bằng đoạn mã C++ sau:
protocol::Audits::ContentSecurityPolicyIssueDetails::create()
.setViolatedDirective(d->violated_directive)
.setIsReportOnly(d->is_report_only)
.setContentSecurityPolicyViolationType(BuildViolationType(
d->content_security_policy_violation_type)))
.build();
Sau khi quyết định thông tin nào cần cung cấp, chúng tôi cần tìm hiểu xem nên lấy thông tin này từ đâu trong Chromium.
Bước 3: phát hiện vấn đề
Để cung cấp thông tin cho Giao thức Chrome DevTools (CDP) theo định dạng được mô tả trong phần cuối, chúng tôi cần tìm nơi thông tin thực sự có sẵn trong phần phụ trợ. May mắn là mã CSP đã có một điểm tắc nghẽn được dùng cho chế độ chỉ báo cáo, nơi chúng ta có thể can thiệp: ContentSecurityPolicy::ReportViolation báo cáo vấn đề đến một điểm cuối báo cáo (không bắt buộc) có thể được định cấu hình trong tiêu đề HTTP của CSP. Hầu hết thông tin chúng tôi muốn báo cáo đều đã có sẵn, vì vậy, chúng tôi không cần phải thay đổi nhiều ở phần phụ trợ để công cụ đo lường hoạt động.
Bước 4: lưu và hiển thị các vấn đề
Một vấn đề nhỏ là chúng tôi cũng muốn báo cáo các vấn đề xảy ra trước khi Công cụ cho nhà phát triển được mở, tương tự như cách xử lý thông báo trên bảng điều khiển. Điều này có nghĩa là chúng tôi không báo cáo ngay các vấn đề cho giao diện người dùng, mà sử dụng một bộ nhớ được điền sẵn các vấn đề, bất kể Công cụ cho nhà phát triển có đang mở hay không. Sau khi mở Công cụ cho nhà phát triển (hoặc bất kỳ ứng dụng CDP nào khác được đính kèm), bạn có thể phát lại tất cả vấn đề đã ghi lại trước đó từ bộ nhớ.
Như vậy là đã xong phần việc ở phần phụ trợ, giờ chúng tôi cần tập trung vào cách hiển thị vấn đề ở giao diện người dùng.
Bước 5: thiết kế văn bản về vấn đề
Thiết kế văn bản về vấn đề là một quy trình có sự tham gia của nhiều nhóm ngoài nhóm của chúng tôi. Ví dụ: chúng tôi thường dựa vào thông tin chi tiết của nhóm triển khai một tính năng (trong trường hợp này là nhóm CSP) và tất nhiên là nhóm DevRel, nhóm thiết kế cách nhà phát triển web xử lý một loại vấn đề nhất định. Văn bản về vấn đề thường trải qua một số bước tinh chỉnh cho đến khi hoàn tất.
Thông thường, nhóm Công cụ cho nhà phát triển sẽ bắt đầu bằng một bản nháp thô về những gì họ hình dung:
## 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/
Sau khi lặp lại, chúng tôi đã đi đến:

Như bạn có thể thấy, việc có sự tham gia của nhóm tính năng và DevRel giúp nội dung mô tả rõ ràng và chính xác hơn nhiều!
Bạn cũng có thể phát hiện các vấn đề về CSP trên trang của mình trong thẻ dành riêng cho các lỗi vi phạm CSP.
Gỡ lỗi các vấn đề về Trusted Types
Việc xử lý TT trên quy mô lớn có thể gặp nhiều khó khăn nếu không có các công cụ phù hợp cho nhà phát triển.
Cải thiện tính năng in bảng điều khiển
Khi làm việc với Đối tượng đáng tin cậy, chúng tôi muốn hiển thị ít nhất là cùng một lượng thông tin như đối với đối tượng không đáng tin cậy. Rất tiếc, hiện tại khi hiển thị một Đối tượng đáng tin cậy, không có thông tin nào về đối tượng được gói được hiển thị.
Đó là vì giá trị hiển thị trong bảng điều khiển được lấy từ việc gọi .valueOf() trên đối tượng theo mặc định. Tuy nhiên, trong trường hợp của Trusted Type, giá trị được trả về không hữu ích lắm. Thay vào đó, chúng tôi muốn có một kết quả tương tự như kết quả bạn nhận được khi gọi .toString(). Để đạt được điều này, chúng ta cần sửa đổi V8 và Blink để giới thiệu cách xử lý đặc biệt cho các đối tượng loại đáng tin cậy.
Mặc dù vì lý do lịch sử, việc xử lý tuỳ chỉnh này được thực hiện trong V8, nhưng phương pháp này có những nhược điểm quan trọng. Có nhiều đối tượng cần hiển thị tuỳ chỉnh nhưng có cùng loại ở cấp JS. Vì V8 là JS thuần tuý, nên nó không thể phân biệt các khái niệm tương ứng với API web, chẳng hạn như Loại đáng tin cậy. Vì lý do đó, V8 phải nhờ trình nhúng (Blink) trợ giúp để phân biệt các đối tượng này.
Do đó, việc chuyển phần mã đó sang Blink hoặc bất kỳ trình nhúng nào có vẻ là một lựa chọn hợp lý. Ngoài vấn đề đã nêu, còn có nhiều lợi ích khác:
- Mỗi trình nhúng có thể có quy trình tạo nội dung mô tả riêng
- Việc tạo nội dung mô tả thông qua Blink API dễ dàng hơn nhiều
- Blink có quyền truy cập vào định nghĩa ban đầu của đối tượng. Do đó, nếu chúng ta sử dụng
.toString()để tạo nội dung mô tả, thì sẽ không có nguy cơ.toString()có thể được xác định lại.
Break-on-violation (ở chế độ chỉ báo cáo)
Hiện tại, cách duy nhất để gỡ lỗi các lỗi vi phạm TT là đặt điểm ngắt cho các ngoại lệ JS. Vì các lỗi vi phạm TT được thực thi sẽ kích hoạt một ngoại lệ, nên tính năng này có thể hữu ích theo một cách nào đó. Tuy nhiên, trong các trường hợp thực tế, bạn cần kiểm soát chi tiết hơn đối với các lỗi vi phạm TT. Cụ thể, chúng tôi chỉ muốn ngắt khi có lỗi vi phạm TT (không phải các ngoại lệ khác), ngắt cả ở chế độ chỉ báo cáo và phân biệt giữa các loại lỗi vi phạm TT.
Công cụ cho nhà phát triển đã hỗ trợ nhiều loại điểm ngắt nên cấu trúc này có thể mở rộng khá nhiều. Để thêm một loại điểm ngắt mới, bạn cần thay đổi phần phụ trợ (Blink), CDP và giao diện người dùng.
Chúng ta nên giới thiệu một lệnh CDP mới, hãy gọi lệnh đó là setBreakOnTTViolation. Lệnh này sẽ được giao diện người dùng sử dụng để cho phần phụ trợ biết loại lỗi vi phạm TT nào cần ngắt. Phần phụ trợ, cụ thể là InspectorDOMDebuggerAgent, sẽ cung cấp một "đầu dò" onTTViolation() được gọi mỗi khi xảy ra lỗi vi phạm TT. Sau đó, InspectorDOMDebuggerAgent sẽ kiểm tra xem lỗi vi phạm đó có kích hoạt điểm ngắt hay không. Nếu có, công cụ này sẽ gửi thông báo đến giao diện người dùng để tạm dừng quá trình thực thi.
Những việc đã làm và việc cần làm tiếp theo
Kể từ khi các vấn đề được mô tả ở đây xuất hiện, thẻ Vấn đề đã có một số thay đổi:
- Khả năng kết nối của bảng điều khiển này với các bảng điều khiển khác trong Công cụ cho nhà phát triển đã được cải thiện.
- Báo cáo về một số vấn đề khác đã được chuyển sang thẻ Vấn đề: độ tương phản thấp, hoạt động đáng tin cậy trên web, chế độ tương thích ngược, attribution reporting API và các vấn đề liên quan đến CORS, cùng nhiều vấn đề khác.
- Ra mắt cơ hội ẩn vấn đề
Trong tương lai, chúng tôi dự định sử dụng thẻ Vấn đề để hiển thị thêm nhiều vấn đề, nhờ đó có thể giảm tải cho Bảng điều khiển khỏi luồng thông báo lỗi khó đọc về lâu dài.
Tải các kênh xem trước xuống
Hãy cân nhắc sử dụng Chrome Canary, Dev hoặc Beta làm trình duyệt phát triển mặc định. Các kênh xem trước này cho phép bạn sử dụng các tính năng mới nhất của Công cụ cho nhà phát triển, kiểm thử các API nền tảng web tiên tiến và giúp bạn tìm thấy vấn đề trên trang web của mình trước khi người dùng phát hiện ra!
Liên hệ với nhóm Chrome DevTools
Hãy sử dụng các lựa chọn sau để thảo luận về các tính năng mới, bản cập nhật hoặc bất kỳ nội dung nào khác liên quan đến Công cụ cho nhà phát triển.
- Gửi ý kiến phản hồi và yêu cầu về tính năng cho chúng tôi tại crbug.com.
- Báo cáo vấn đề về Công cụ cho nhà phát triển bằng cách nhấp vào biểu tượng Tuỳ chọn khác > Trợ giúp > Báo cáo vấn đề về Công cụ cho nhà phát triển trong Công cụ cho nhà phát triển.
- Đăng tweet cho @ChromeDevTools.
- Để lại bình luận về Tính năng mới trong video trên YouTube về Công cụ cho nhà phát triển hoặc Mẹo về Công cụ cho nhà phát triển trong video trên YouTube.