Mengimplementasikan proses debug CSP dan Jenis Tepercaya di Chrome DevTools

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

Postingan blog ini membahas penerapan dukungan DevTools untuk men-debug masalah Kebijakan Keamanan Konten (CSP) dengan bantuan tab Masalah yang baru diperkenalkan.

Pekerjaan implementasi dilakukan selama 2 program magang: 1. Dalam versi pertama, kami membuat framework pelaporan umum dan mendesain pesan masalah untuk 3 masalah pelanggaran CSP. 2. Selama rilis kedua, kami menambahkan masalah Jenis Tepercaya bersama dengan beberapa fitur DevTools khusus untuk proses debug Jenis Tepercaya.

Apa itu Kebijakan Keamanan Konten?

Kebijakan Keamanan Konten (CSP) memungkinkan untuk membatasi perilaku tertentu di situs guna meningkatkan keamanan. Misalnya, CSP dapat digunakan untuk melarang skrip inline atau melarang eval, yang keduanya mengurangi platform serangan untuk serangan Pembuatan Skrip Lintas Situs (XSS). Untuk pengantar CSP yang mendetail, baca di sini.

CSP yang sangat baru adalah kebijakan Trusted Types(TT), yang memungkinkan analisis dinamis yang dapat secara sistematis mencegah berbagai jenis serangan injeksi di situs. Untuk mencapai hal ini, TT mendukung situs dalam memantau kode JavaScript-nya agar hanya mengizinkan jenis hal tertentu yang ditetapkan ke sink DOM seperti innerHTML.

Situs dapat mengaktifkan kebijakan keamanan konten dengan menyertakan header HTTP tertentu. Misalnya, header content-security-policy: require-trusted-types-for 'script'; trusted-types default mengaktifkan kebijakan TT untuk halaman.

Setiap kebijakan dapat beroperasi dalam salah satu mode berikut:

  • enforced mode - di mana setiap pelanggaran kebijakan merupakan error,
  • mode hanya laporan - yang melaporkan pesan error sebagai peringatan, tetapi tidak menyebabkan kegagalan di halaman web.

Menerapkan Masalah Kebijakan Keamanan Konten di tab Masalah

Tujuan pekerjaan ini adalah untuk meningkatkan pengalaman proses debug untuk masalah CSP. Saat mempertimbangkan masalah baru, tim DevTools secara kasar mengikuti proses ini:

  1. Menentukan cerita pengguna. Identifikasi serangkaian cerita pengguna di front-end DevTools yang mencakup bagaimana developer web perlu menyelidiki masalah.
  2. Penerapan frontend. Berdasarkan cerita pengguna, identifikasi informasi yang diperlukan untuk menyelidiki masalah di frontend (misalnya, permintaan terkait, nama cookie, baris dalam skrip atau file html, dll.).
  3. Pendeteksian masalah. Identifikasi tempat di browser tempat masalah dapat terdeteksi di Chrome dan instrumentasikan tempat tersebut untuk melaporkan masalah, termasuk informasi yang relevan dari langkah (2).
  4. Simpan dan tampilkan masalah. Simpan masalah di tempat yang sesuai dan sediakan untuk DevTools setelah dibuka
  5. Mendesain teks masalah. Buat teks penjelasan yang membantu developer web memahami, dan yang lebih penting, memperbaiki masalah

Langkah 1: menentukan cerita pengguna untuk Masalah CSP

Sebelum memulai pekerjaan implementasi, kami membuat dokumen desain dengan cerita pengguna untuk lebih memahami apa yang perlu kami lakukan. Misalnya, kami menulis cerita pengguna berikut:


Sebagai developer, yang baru saja menyadari bahwa beberapa bagian situs saya diblokir, saya ingin:- - ...menemukan tahu apakah CSP adalah alasan iframe / gambar di situs saya diblokir - ...mempelajari perintah CSP mana yang menyebabkan pemblokiran resource tertentu - ...mengetahui cara mengubah CSP situs saya untuk mengizinkan tampilan resource yang saat ini diblokir / eksekusi js yang saat ini diblokir.


Untuk mempelajari cerita pengguna ini, kami membuat beberapa contoh halaman web sederhana yang menampilkan pelanggaran CSP yang kami minati, dan mempelajari halaman contoh untuk memahami prosesnya sendiri. Berikut adalah beberapa contoh halaman web (buka demo dengan tab Masalah terbuka):

Dengan menggunakan proses ini, kami mengetahui bahwa lokasi sumber adalah bagian informasi yang paling penting untuk men-debug masalah CSP. Kami juga merasa bahwa menemukan iframe dan permintaan terkait dengan cepat berguna jika resource diblokir, dan link langsung ke elemen HTML di panel Elements di DevTools juga dapat berguna.

Langkah 2: implementasi frontend

Kita mengubah insight ini menjadi draf pertama informasi yang ingin kami sediakan bagi DevTools melalui Protokol Chrome DevTools (CDP):

Berikut adalah kutipan dari 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

Definisi di atas pada dasarnya mengenkode struktur data JSON. Hal ini ditulis dalam bahasa sederhana yang disebut PDL (protokol data language). PDL digunakan untuk dua tujuan. Pertama, kita menggunakan PDL untuk menghasilkan definisi TypeScript yang diandalkan front-end DevTools. Misalnya, definisi PDL di atas menghasilkan antarmuka TypeScript berikut:

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;
}

Kedua, dan mungkin yang lebih penting, kita membuat library C++ dari definisi yang menangani pembuatan dan pengiriman struktur data ini dari backend Chromium C++ ke frontend DevTools. Dengan library tersebut, objek ContentSecurityPolicyIssueDetails dapat dibuat menggunakan potongan kode C++ berikut:

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

Setelah menentukan informasi mana yang ingin kami sediakan, kami perlu mencari tahu tempat untuk mendapatkan informasi ini dari Chromium.

Langkah 3: deteksi masalah

Agar informasi tersedia untuk Chrome DevTools Protocol (CDP) dalam format yang dijelaskan di bagian terakhir, kita perlu menemukan tempat informasi tersebut benar-benar tersedia di backend. Untungnya, kode CSP sudah memiliki bottleneck yang digunakan untuk mode khusus laporan, tempat kita dapat terhubung ke: ContentSecurityPolicy::ReportViolation melaporkan masalah ke endpoint pelaporan (opsional) yang dapat dikonfigurasi di header HTTP CSP. Sebagian besar informasi yang ingin kami laporkan sudah tersedia, sehingga tidak ada perubahan besar di backend yang diperlukan agar instrumentasi kami berfungsi.

Langkah 4: simpan dan tampilkan masalah

Komplikasi kecilnya adalah fakta bahwa kita juga ingin melaporkan masalah yang terjadi sebelum DevTools dibuka, mirip dengan cara pesan konsol ditangani. Ini berarti bahwa kita tidak melaporkan masalah secara langsung ke front-end, tetapi menggunakan penyimpanan yang diisi dengan masalah secara terpisah dari apakah DevTools terbuka atau tidak. Setelah DevTools dibuka (atau, klien CDP lainnya dilampirkan), semua masalah yang direkam sebelumnya dapat diputar ulang dari penyimpanan.

Ini mengakhiri pekerjaan backend, dan sekarang kita perlu berfokus pada cara menampilkan masalah di frontend.

Langkah 5: mendesain teks masalah

Mendesain teks masalah adalah proses yang melibatkan beberapa tim selain tim kami sendiri, misalnya, kami sering mengandalkan insight dari tim yang menerapkan fitur (dalam hal ini adalah tim CSP) dan tentu saja tim DevRel, yang mendesain cara developer web menangani jenis masalah tertentu. Teks masalah biasanya mengalami beberapa penyempurnaan hingga selesai.

Biasanya, tim DevTools akan memulai dengan draf kasar dari apa yang mereka bayangkan:


## 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/

Setelah iterasi, kita akan sampai pada:

ALT_TEXT_HERE

Seperti yang Anda lihat, melibatkan tim fitur dan DevRel membuat deskripsi jauh lebih jelas dan tepat!

Masalah CSP di halaman Anda juga dapat ditemukan di tab yang secara khusus ditujukan untuk pelanggaran CSP.

Men-debug masalah Jenis Tepercaya

Bekerja dengan TT dalam skala besar dapat menjadi tantangan tanpa alat developer yang tepat.

Pencetakan konsol yang ditingkatkan

Saat menggunakan Objek Tepercaya, kita ingin menampilkan setidaknya jumlah informasi yang sama seperti untuk objek yang tidak tepercaya. Sayangnya, saat ini saat menampilkan Objek Tepercaya, tidak ada informasi tentang objek yang digabungkan yang ditampilkan.

Hal ini karena nilai yang ditampilkan di konsol diambil dari panggilan .valueOf() pada objek secara default. Namun, dalam kasus Jenis Tepercaya, nilai yang ditampilkan tidak terlalu berguna. Sebagai gantinya, kita ingin memiliki sesuatu yang mirip dengan yang Anda dapatkan saat memanggil .toString(). Untuk mencapai hal ini, kita perlu memodifikasi V8 dan Blink untuk memperkenalkan penanganan khusus untuk objek bertipe tepercaya.

Meskipun karena alasan historis, penanganan kustom ini dilakukan di V8, pendekatan seperti ini memiliki kekurangan penting. Ada banyak objek yang perlu menampilkan kustom, tetapi jenisnya sama di tingkat JS. Karena V8 adalah JS murni, V8 tidak dapat membedakan konsep yang sesuai dengan Web API seperti Jenis Tepercaya. Oleh karena itu, V8 harus meminta bantuan penyertanya (Blink) untuk membedakannya.

Oleh karena itu, memindahkan bagian kode tersebut ke Blink atau penyempan tampaknya merupakan pilihan yang logis. Selain masalah yang terekspos, ada banyak manfaat lainnya:

  • Setiap sematan dapat memiliki pembuatan deskripsinya sendiri
  • Membuat deskripsi melalui Blink API jauh lebih mudah
  • Blink memiliki akses ke definisi asli objek. Jadi, jika kita menggunakan .toString() untuk membuat deskripsi, tidak ada risiko bahwa .toString() mungkin didefinisikan ulang.

Jeda saat terjadi pelanggaran (dalam mode laporan saja)

Saat ini, satu-satunya cara untuk melakukan debug pelanggaran TT adalah dengan menetapkan titik henti sementara pada pengecualian JS. Karena pelanggaran TT yang diterapkan akan memicu pengecualian, fitur ini bisa berguna. Namun, dalam skenario dunia nyata, Anda memerlukan kontrol yang lebih terperinci atas pelanggaran TT. Secara khusus, kami ingin membuat pemisahan hanya pada pelanggaran TT (bukan pengecualian lainnya), membuat pemisahan juga dalam mode hanya laporan, dan membedakan berbagai jenis pelanggaran TT.

DevTools sudah memiliki dukungan untuk berbagai titik henti sementara sehingga arsitekturnya cukup dapat diperluas. Menambahkan jenis titik henti sementara baru memerlukan perubahan di backend (Blink), CDP, dan frontend. Kita harus memperkenalkan perintah CDP baru, sebut saja setBreakOnTTViolation. Perintah ini akan digunakan oleh frontend untuk memberi tahu backend tentang jenis pelanggaran TT yang harus dilanggar. Backend, khususnya InspectorDOMDebuggerAgent, akan menyediakan "probe", onTTViolation() yang akan dipanggil setiap kali terjadi pelanggaran TT. Kemudian, InspectorDOMDebuggerAgent akan memeriksa apakah pelanggaran tersebut harus memicu titik henti sementara, dan jika demikian, InspectorDOMDebuggerAgent akan mengirim pesan ke frontend untuk menjeda eksekusi.

Apa yang sudah dilakukan dan apa yang akan dilakukan selanjutnya?

Sejak masalah yang dijelaskan di sini diperkenalkan, tab Masalah telah mengalami beberapa perubahan:

Ke depannya, kami berencana menggunakan tab Masalah untuk menampilkan lebih banyak masalah, yang akan memungkinkan Konsol untuk menghapus alur pesan error yang tidak dapat dibaca dalam jangka panjang.

Mendownload saluran pratinjau

Sebaiknya gunakan Chrome Canary, Dev, atau Beta sebagai browser pengembangan default Anda. Saluran pratinjau ini memberi Anda akses ke fitur DevTools terbaru, memungkinkan Anda menguji API platform web canggih, dan membantu Anda menemukan masalah di situs sebelum pengguna melakukannya.

Hubungi tim Chrome DevTools

Gunakan opsi berikut untuk membahas fitur baru, update, atau hal lain yang terkait dengan DevTools.