Sistem ekstensi Chrome menerapkan Kebijakan Keamanan Konten (CSP) default yang cukup ketat.
Pembatasan kebijakannya sangat jelas: skrip harus dipindahkan keluar baris menjadi
File JavaScript, pengendali peristiwa inline harus dikonversi untuk menggunakan addEventListener
, dan eval()
adalah
dinonaktifkan. Aplikasi Chrome memiliki kebijakan yang lebih ketat, dan kami cukup puas dengan properti keamanan
yang disediakan oleh kebijakan ini.
Namun, kami menyadari bahwa berbagai library menggunakan konstruksi seperti eval()
dan eval
seperti
new Function()
untuk pengoptimalan performa dan kemudahan ekspresi. Library template
terutama rentan terhadap gaya implementasi ini. Meskipun beberapa framework (seperti Angular.js) mendukung CSP secara langsung, banyak framework populer yang belum diupdate ke mekanisme yang kompatibel dengan dunia tanpa eval
ekstensi. Oleh karena itu, menghapus dukungan untuk fungsi tersebut terbukti lebih
bermasalah dari yang diharapkan bagi developer.
Dokumen ini memperkenalkan sandbox sebagai mekanisme aman untuk menyertakan library ini dalam project Anda tanpa mengorbankan keamanan. Untuk singkatnya, kami akan menggunakan istilah ekstensi secara keseluruhan, tapi konsep ini berlaku sama untuk aplikasi.
Mengapa menggunakan sandbox?
eval
berbahaya di dalam ekstensi karena kode yang dieksekusi memiliki akses ke semua hal di lingkungan izin tinggi ekstensi. Ada banyak API chrome.*
canggih yang tersedia dan dapat
berdampak serius pada keamanan dan privasi pengguna; ekstraksi data sederhana adalah hal yang paling tidak perlu dikhawatirkan.
Solusi yang ditawarkan adalah sandbox tempat eval
dapat mengeksekusi kode tanpa akses ke
data ekstensi atau API bernilai tinggi ekstensi. Tidak ada data, tidak ada API, tidak masalah.
Kami melakukannya dengan mencantumkan file HTML tertentu di dalam paket ekstensi sebagai yang di-sandbox.
Setiap kali dimuat, halaman dengan sandbox akan dipindahkan ke asal unik, dan akan ditolak aksesnya ke API chrome.*
. Jika kita memuat halaman yang di-sandbox ini ke dalam ekstensi melalui iframe
, kita bisa
meneruskan pesannya, membiarkannya bertindak terhadap pesan itu
dengan cara tertentu, dan menunggunya memberikan kembali
hasil pengujian tersebut. Mekanisme pesan sederhana ini memberi kita semua yang diperlukan untuk menyertakan kode yang didorong eval
dengan aman dalam alur kerja ekstensi.
Membuat dan menggunakan sandbox.
Jika Anda ingin langsung mempelajari kode, ambil ekstensi contoh sandboxing dan mulai. Ini adalah contoh kerja API pesan kecil yang dibuat di atas library template Handlebars, dan akan memberi Anda semua yang diperlukan untuk memulai. Bagi Anda yang ingin seperti sedikit penjelasan lebih lanjut, mari kita kita bahas contoh itu bersama-sama di sini.
Mencantumkan file dalam manifes
Setiap file yang harus dijalankan di dalam sandbox harus dicantumkan dalam manifes ekstensi dengan menambahkan properti sandbox
. Ini adalah langkah yang penting, dan mudah dilupakan, jadi periksa kembali apakah
file yang telah di-sandbox akan tercantum di manifes. Dalam contoh ini, kami meng-{i>sandbox<i} file dengan cerdas
bernama "sandbox.html". Entri manifes terlihat seperti ini:
{
...,
"sandbox": {
"pages": ["sandbox.html"]
},
...
}
Memuat file dalam sandbox
Untuk melakukan sesuatu yang menarik dengan file {i>sandbox<i}, kita perlu mengunggahnya dalam konteks di mana
dapat ditangani oleh kode ekstensi. Di sini, sandbox.html telah dimuat ke dalam Halaman Peristiwa ekstensi (eventpage.html) melalui iframe
. eventpage.js berisi kode
yang mengirim pesan ke sandbox setiap kali tindakan browser diklik dengan mencari iframe
di halaman, dan menjalankan metode postMessage
di contentWindow
. Pesan adalah objek
yang berisi dua properti: context
dan command
. Kita akan membahas keduanya sebentar lagi.
chrome.browserAction.onClicked.addListener(function() {
var iframe = document.getElementById('theFrame');
var message = {
command: 'render',
context: {thing: 'world'}
};
iframe.contentWindow.postMessage(message, '*');
});
postMessage
API, lihat dokumentasi postMessage
di MDN . Konten ini cukup lengkap dan layak dibaca. Secara khusus, perlu diperhatikan bahwa data hanya dapat diteruskan bolak-balik jika dapat diserialisasi. Fungsi, misalnya, tidak bersifat umum.Melakukan sesuatu yang berbahaya
Saat dimuat, sandbox.html
akan memuat library Handlebars, serta membuat dan mengompilasi template inline
dengan cara yang disarankan Handlebars:
<script src="handlebars-1.0.0.beta.6.js"></script>
<script id="hello-world-template" type="text/x-handlebars-template">
<div class="entry">
<h1>Hello, !</h1>
</div>
</script>
<script>
var templates = [];
var source = document.getElementById('hello-world-template').innerHTML;
templates['hello'] = Handlebars.compile(source);
</script>
Langkah ini tidak gagal! Meskipun Handlebars.compile
akhirnya menggunakan new Function
, semuanya berfungsi
persis seperti yang diharapkan, dan kita mendapatkan template yang dikompilasi di templates['hello']
.
Meneruskan hasilnya kembali
Kami akan menyediakan template ini untuk digunakan dengan menyiapkan pemroses pesan yang menerima perintah
dari Halaman Peristiwa. Kita akan menggunakan command
yang diteruskan untuk menentukan apa yang harus dilakukan (Anda dapat
membayangkan melakukan lebih dari sekadar merender; mungkin membuat template? Mungkin mengelolanya dengan cara
tertentu?), dan context
akan diteruskan ke template secara langsung untuk rendering. HTML yang dirender akan diteruskan kembali ke Halaman Peristiwa sehingga ekstensi dapat melakukan sesuatu yang berguna dengannya nanti:
<script>
window.addEventListener('message', function(event) {
var command = event.data.command;
var name = event.data.name || 'hello';
switch(command) {
case 'render':
event.source.postMessage({
name: name,
html: templates[name](event.data.context)
}, event.origin);
break;
// case 'somethingElse':
// ...
}
});
</script>
Kembali di Halaman Peristiwa, kita akan menerima pesan ini, dan melakukan sesuatu yang menarik dengan data html
yang telah diteruskan kepada kita. Dalam hal ini, kita hanya akan menggemakannya melalui Notifikasi Desktop, tetapi
HTML ini dapat digunakan dengan aman
sebagai bagian dari UI ekstensi. Menyisipkannya melalui
innerHTML
tidak menimbulkan risiko keamanan yang signifikan, karena bahkan kompromi lengkap terhadap kode sandbox
melalui beberapa serangan cerdas tidak akan dapat memasukkan konten plugin atau skrip berbahaya ke dalam
konteks ekstensi dengan izin tinggi.
Mekanisme ini membuat pembuatan template menjadi mudah, tetapi tentu saja tidak terbatas pada pembuatan template. Setiap kode yang tidak berfungsi secara otomatis berdasarkan Kebijakan Keamanan Konten yang ketat dapat di-sandbox. Faktanya, sering kali berguna untuk membuat sandbox komponen ekstensi yang akan berjalan dengan benar guna membatasi setiap bagian program ke kumpulan hak istimewa terkecil yang diperlukan agar dapat dijalankan dengan benar. Presentasi Menulis Aplikasi Web dan Ekstensi Chrome yang Aman dari Google I/O 2012 memberikan beberapa contoh bagus tentang penerapan teknik ini, dan Anda akan menghabiskan waktu 56 menit untuk menontonnya.