DOMPurify adalah pembersih XSS khusus DOM, super cepat, dan sangat toleran untuk HTML, MathML, dan SVG.
Ini juga sangat mudah digunakan dan memulai. DOMPurify dimulai pada Februari 2014 dan telah mencapai versi v3.2.1 .
DOMPurify ditulis dalam JavaScript dan berfungsi di semua browser modern (Safari (10+), Opera (15+), Edge, Firefox, dan Chrome - serta hampir semua browser lain yang menggunakan Blink, Gecko, atau WebKit). Itu tidak rusak pada MSIE atau browser lawas lainnya. Itu tidak menghasilkan apa-apa.
Perhatikan bahwa DOMPurify v2.5.7 adalah versi terbaru yang mendukung MSIE. Untuk pembaruan keamanan penting yang kompatibel dengan MSIE, silakan gunakan cabang 2.x.
Pengujian otomatis kami mencakup 24 browser berbeda saat ini, dan masih banyak lagi yang akan datang. Kami juga membahas Node.js v16.x, v17.x, v18.x dan v19.x, menjalankan DOMPurify di jsdom. Versi Node yang lebih lama diketahui juga berfungsi, tapi hei... tidak ada jaminan.
DOMPurify ditulis oleh petugas keamanan yang memiliki latar belakang luas dalam serangan web dan XSS. Jangan takut. Untuk lebih jelasnya silakan baca juga tentang Sasaran Keamanan & Model Ancaman kami. Tolong, bacalah. Benar sekali.
DOMPurify membersihkan HTML dan mencegah serangan XSS. Anda dapat memberi makan DOMPurify dengan string penuh HTML kotor dan itu akan mengembalikan string (kecuali dikonfigurasi sebaliknya) dengan HTML bersih. DOMPurify akan menghapus segala sesuatu yang mengandung HTML berbahaya dan dengan demikian mencegah serangan XSS dan hal-hal buruk lainnya. Ini juga sangat cepat. Kami menggunakan teknologi yang disediakan browser dan mengubahnya menjadi filter XSS. Semakin cepat browser Anda, semakin cepat DOMPurifynya.
Itu mudah. Cukup sertakan DOMPurify di situs web Anda.
<skrip type="text/javascript" src="src/purify.js"></script>
<skrip type="text/javascript" src="dist/purify.min.js"></script>
Setelah itu Anda dapat membersihkan string dengan menjalankan kode berikut:
const clean = DOMPurify.sanitize(kotor);
Atau mungkin ini, jika Anda suka bekerja dengan Angular atau sejenisnya:
import DOMPurify dari 'dompurify';const clean = DOMPurify.sanitize('<b>halo</b>');
HTML yang dihasilkan dapat ditulis ke dalam elemen DOM menggunakan innerHTML
atau DOM menggunakan document.write()
. Itu sepenuhnya terserah Anda. Perhatikan bahwa secara default, kami mengizinkan HTML, SVG dan MathML. Jika Anda hanya memerlukan HTML, yang mungkin merupakan kasus penggunaan yang sangat umum, Anda juga dapat mengaturnya dengan mudah:
const clean = DOMPurify.sanitize(kotor, { USE_PROFILES: { html: true } });
Harap dicatat, jika Anda terlebih dahulu membersihkan HTML dan kemudian memodifikasinya setelahnya , Anda mungkin dengan mudah menghilangkan efek sanitasi . Jika Anda memasukkan markup yang telah disanitasi ke perpustakaan lain setelah sanitasi, harap pastikan bahwa perpustakaan tersebut tidak mengacaukan HTML-nya sendiri.
Setelah membersihkan markup, Anda juga dapat melihat properti DOMPurify.removed
dan mencari tahu elemen dan atribut apa yang dibuang. Harap jangan menggunakan properti ini untuk membuat keputusan penting tentang keamanan. Ini hanyalah sedikit bantuan bagi mereka yang penasaran.
DOMPurify secara teknis juga berfungsi di sisi server dengan Node.js. Dukungan kami berupaya mengikuti siklus rilis Node.js.
Menjalankan DOMPurify di server memerlukan kehadiran DOM, yang mungkin tidak mengejutkan. Biasanya jsdom adalah alat pilihan dan kami sangat menyarankan untuk menggunakan jsdom versi terbaru.
Mengapa? Karena versi jsdom yang lebih lama diketahui bermasalah sehingga menghasilkan XSS meskipun DOMPurify melakukan semuanya 100% dengan benar. Ada vektor serangan yang diketahui , misalnya jsdom v19.0.0 yang diperbaiki di jsdom v20.0.0 - dan kami sangat menyarankan untuk selalu memperbarui jsdom karena itu.
Perlu diketahui juga bahwa alat seperti happy-dom ada tetapi tidak dianggap aman pada saat ini. Menggabungkan DOMPurify dengan happy-dom saat ini tidak disarankan dan kemungkinan besar akan menghasilkan XSS.
Selain itu, Anda boleh menggunakan DOMPurify di server. Mungkin. Ini sangat tergantung pada jsdom atau DOM apa pun yang Anda gunakan di sisi server. Jika Anda bisa menerimanya, inilah cara Anda membuatnya berfungsi:
npm instal dopurify npm instal jsdom
Untuk jsdom (harap gunakan versi terbaru), ini akan berhasil:
const createDOMPurify = memerlukan('dompurify');const { JSDOM } = memerlukan('jsdom');const window = new JSDOM('').window;const DOMPurify = createDOMPurify(window);const clean = DOMPurify.sanitize(' <b>halo</b>');
Atau bahkan ini, jika Anda lebih suka bekerja dengan impor:
impor { JSDOM } dari 'jsdom';impor DOMPurify dari 'dompurify';const window = new JSDOM('').window;const purify = DOMPurify(window);const clean = purify.sanitize('<b>halo< /b>');
Jika Anda memiliki masalah dalam membuatnya berfungsi dalam pengaturan spesifik Anda, pertimbangkan untuk melihat proyek dompurify isomorfik luar biasa yang memecahkan banyak masalah yang mungkin dihadapi orang.
npm install isomorfik-dompurify
import DOMPurify dari 'isomorphic-dompurify';const clean = DOMPurify.sanitize('<s>hello</s>');
Tentu saja ada demonya! Mainkan dengan DOMPurify
Pertama-tama, harap segera menghubungi kami melalui email agar kami dapat melakukan perbaikan. kunci PGP
Selain itu, Anda mungkin memenuhi syarat untuk mendapatkan bug bounty! Orang-orang baik di Fastmail menggunakan DOMPurify untuk layanan mereka dan menambahkan perpustakaan kami ke cakupan bug bounty mereka. Jadi, jika Anda menemukan cara untuk melewati atau melemahkan DOMPurify, silakan lihat juga situs web mereka dan info bug bounty.
Seperti apa tampilan markup yang dimurnikan? Nah, demonya menunjukkan banyak elemen buruk. Namun mari kita tunjukkan juga beberapa contoh kecil!
DOMPurify.sanitize('<img src=x onerror=alert(1)//>'); // menjadi <img src="x">DOMPurify.sanitize('<svg><g/onload=alert(2)//<p>'); // menjadi <svg><g></g></svg>DOMPurify.sanitize('<p>abc<iframe//src=jAva	script:alert(3)>def</p>'); // menjadi <p>abc</p>DOMPurify.sanitize('<math><mi//xlink:href="data:x,<script>alert(4)</script>">'); // menjadi <math><mi></mi></math>DOMPurify.sanitize('<TABLE><tr><td>HELLO</tr></TABL>'); // menjadi <table><tbody><tr><td>HELLO</td></tr></tbody></table>DOMPurify.sanitize('<UL><li><A HREF=//google .com>klik</UL>'); // menjadi <ul><li><a href="//google.com">klik</a></li></ul>
DOMPurify saat ini mendukung HTML5, SVG dan MathML. DOMPurify secara default mengizinkan CSS, atribut data khusus HTML. DOMPurify juga mendukung Shadow DOM - dan membersihkan template DOM secara rekursif. DOMPurify juga memungkinkan Anda membersihkan HTML untuk digunakan dengan jQuery $()
dan elm.html()
API tanpa masalah apa pun.
DOMPurify tidak melakukan apa pun. Ini hanya mengembalikan string yang Anda masukkan. DOMPurify memperlihatkan properti bernama isSupported
, yang memberi tahu Anda apakah properti tersebut dapat melakukan tugasnya, sehingga Anda dapat membuat rencana cadangan Anda sendiri.
Di versi 1.0.9, dukungan untuk Trusted Types API telah ditambahkan ke DOMPurify. Di versi 2.0.0, flag konfigurasi ditambahkan untuk mengontrol perilaku DOMPurify terkait hal ini.
Ketika DOMPurify.sanitize
digunakan dalam lingkungan di mana Trusted Types API tersedia dan RETURN_TRUSTED_TYPE
diatur ke true
, ia mencoba mengembalikan nilai TrustedHTML
alih-alih string (perilaku untuk opsi konfigurasi RETURN_DOM
dan RETURN_DOM_FRAGMENT
tidak berubah).
Perhatikan bahwa untuk membuat kebijakan di trustedTypes
menggunakan DOMPurify, RETURN_TRUSTED_TYPE: false
diperlukan, karena createHTML
mengharapkan string normal, bukan TrustedHTML
. Contoh di bawah menunjukkan hal ini.
window.trustedTypes!.createPolicy('default', { createHTML: (to_escape) =>DOMPurify.sanitize(to_escape, { RETURN_TRUSTED_TYPE: false }),});
Ya. Nilai konfigurasi default yang disertakan sudah cukup bagus - tetapi tentu saja Anda dapat menggantinya. Periksa folder /demos
untuk melihat banyak contoh tentang bagaimana Anda dapat menyesuaikan DOMPurify.
// menghapus {{ ... }}, ${ ... } dan <% ... %> untuk membuat keluaran aman untuk sistem templat// harap berhati-hati, mode ini tidak disarankan untuk penggunaan produksi.// mengizinkan penguraian template dalam HTML yang dikontrol pengguna tidak disarankan sama sekali.// hanya gunakan mode ini jika benar-benar tidak ada alternatif.const clean = DOMPurify.sanitize(dirty, {SAFE_FOR_TEMPLATES: true});// ubah caranya misalnya komentar yang mengandung risiko Karakter HTML adalah diperlakukan.// berhati-hatilah, pengaturan ini hanya boleh disetel ke `false` jika Anda benar-benar hanya menangani // HTML dan tidak ada yang lain, tidak ada SVG, MathML atau sejenisnya. // Jika tidak, mengubah dari `true` menjadi `false` akan menyebabkan XSS dengan cara ini atau cara lainnya.const clean = DOMPurify.sanitize(dirty, {SAFE_FOR_XML: false});
// izinkan hanya elemen <b>, sangat strictconst clean = DOMPurify.sanitize(dirty, {ALLOWED_TAGS: ['b']});// izinkan hanya <b> dan <q> dengan atribut gayaconst clean = DOMPurify.sanitize( kotor, {ALLOWED_TAGS: ['b', 'q'], ALLOWED_ATTR: ['style']});// mengizinkan semua elemen HTML yang aman kecuali SVG atau MathML// perhatikan bahwa pengaturan USE_PROFILES akan menggantikan pengaturan ALLOWED_TAGS // jadi jangan menggunakannya bersama-samaconst clean = DOMPurify.sanitize(dirty, {USE_PROFILES: {html: true}});// izinkan semua elemen SVG dan SVG yang aman Filter, tanpa HTML atau MathMLconst clean = DOMPurify.sanitize(dirty, {USE_PROFILES: {svg: true, svgFilters: true}});// mengizinkan semua elemen MathML dan SVG yang aman, tetapi tidak ada Filter SVGconst clean = DOMPurify.sanitize(dirty, {USE_PROFILES: {mathMl: true, svg: true}});// ubah namespace default dari HTML ke sesuatu yang berbedaconst clean = DOMPurify.sanitize(dirty, {NAMESPACE: 'http://www.w3.org/2000/svg'});// biarkan semua HTML aman apa adanya dan tambahkan elemen <style> ke block-listconst clean = DOMPurify.sanitize(dirty, {FORBID_TAGS: [' style']});// biarkan semua HTML aman apa adanya dan tambahkan atribut style ke block-listconst clean = DOMPurify.sanitize(dirty, {FORBID_ATTR: ['style']});// memperluas array tag yang diperbolehkan dan menambahkan <my-tag> keallow-listconst clean = DOMPurify.sanitize(dirty, {ADD_TAGS: ['my-tag']});/ / memperluas array atribut yang diizinkan dan menambahkan my-attr keallow-listconst clean = DOMPurify.sanitize(dirty, {ADD_ATTR: ['my-attr']});// melarang atribut ARIA, biarkan HTML aman lainnya apa adanya (defaultnya benar)const clean = DOMPurify.sanitize(dirty, {ALLOW_ARIA_ATTR: false});// larang atribut data HTML5, biarkan HTML aman lainnya apa adanya (defaultnya benar)const clean = DOMPurify. membersihkan(kotor, {ALLOW_DATA_ATTR: false});
// DOMPurify memungkinkan untuk menentukan aturan untuk Elemen Kustom. Saat menggunakan literal CUSTOM_ELEMENT_HANDLING//, dimungkinkan untuk menentukan dengan tepat elemen apa yang ingin Anda izinkan (secara default, tidak ada yang diizinkan).//// Hal yang sama berlaku untuk atributnya. Secara default, Allow.list bawaan atau dikonfigurasi digunakan.//// Anda dapat menggunakan literal RegExp untuk menentukan apa yang diperbolehkan atau predikat, contoh keduanya dapat dilihat di bawah.// Nilai default sangat membatasi untuk mencegah bypass XSS yang tidak disengaja. Tangani dengan sangat hati-hati!const clean = DOMPurify.sanitize('<foo-bar baz="foobar" banned="true"></foo-bar><div is="foo-baz"></div>', {CUSTOM_ELEMENT_HANDLING: {tagNameCheck: null, // tidak ada elemen khusus yang diizinkanattributeNameCheck: null, // daftar izin atribut default/standar digunakanallowCustomizedBuiltInElements: false, // tidak disesuaikan bawaan diperbolehkan},}); // <div is=""></div>const clean = DOMPurify.sanitize('<foo-bar baz="foobar" banned="true"></foo-bar><div is="foo-baz "></div>',{CUSTOM_ELEMENT_HANDLING: {tagNameCheck: /^foo-/, // izinkan semua tag yang dimulai dengan "foo-"attributeNameCheck: /baz/, // izinkan semua atribut yang mengandung "baz"allowCustomizedBuiltInElements: true, // bawaan yang disesuaikan diperbolehkan},}); // <foo-bar baz="foobar"></foo-bar><div is="foo-baz"></div>const clean = DOMPurify.sanitize('<foo-bar baz="foobar" dilarang ="true"></foo-bar><div is="foo-baz"></div>',{CUSTOM_ELEMENT_HANDLING: {tagNameCheck: (tagName) => tagName.match(/^foo-/), // izinkan semua tag yang dimulai dengan "foo-"attributeNameCheck: (attr) => attr.match(/baz/), // izinkan semua tag yang mengandung "baz"allowCustomizedBuiltInElements: true, // izinkan bawaan yang disesuaikan},}); // <foo-bar baz="foobar"></foo-bar><div is="foo-baz"></div>
// memperluas array elemen yang ada yang dapat menggunakan Data URIsconst clean = DOMPurify.sanitize(dirty, {ADD_DATA_URI_TAGS: ['a', 'area']});// memperluas array elemen yang aman untuk URI- nilai seperti (hati-hati, risiko XSS)const clean = DOMPurify.sanitize(dirty, {ADD_URI_SAFE_ATTR: ['attr-saya']});
// izinkan penangan protokol eksternal dalam atribut URL (defaultnya salah, hati-hati, risiko XSS) // secara default hanya http, https, ftp, ftps, tel, mailto, callto, sms, cid dan xmpp yang diperbolehkan.const clean = DOMPurify.sanitize(dirty, {ALLOW_UNKNOWN_PROTOCOLS: true});// mengizinkan penangan protokol tertentu dalam atribut URL melalui regex (defaultnya salah, jadilah hati-hati, risiko XSS)// secara default hanya http, https, ftp, ftps, tel, mailto, callto, sms, cid dan xmpp yang diperbolehkan.// RegExp Default: /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^az]|[a-z+.-]+(?:[^ a-z+.-:]|$))/i;const clean = DOMPurify.sanitize(kotor, {ALLOWED_URI_REGEXP: /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|xxx):|[^az]|[a-z+.-]+(?: [^a-z+.-:]|$))/i});
// mengembalikan DOM HTMLBodyElement sebagai pengganti string HTML (defaultnya salah)const clean = DOMPurify.sanitize(dirty, {RETURN_DOM: true});// mengembalikan DOM DocumentFragment sebagai ganti string HTML (defaultnya salah)const clean = DOMPurify.sanitize(dirty, {RETURN_DOM_FRAGMENT: true});// gunakan tanda RETURN_TRUSTED_TYPE untuk aktifkan dukungan Jenis Tepercaya jika tersediaconst clean = DOMPurify.sanitize(dirty, {RETURN_TRUSTED_TYPE: true}); // akan mengembalikan objek TrustedHTML dan bukan string jika memungkinkan// menggunakan Trusted Type policyconst clean = DOMPurify.sanitize(dirty, {// kebijakan yang disediakan harus mendefinisikan createHTML dan createScriptURLTRUSTED_TYPES_POLICY: trustTypes.createPolicy({createHTML(s) { return s},createScriptURL(s) { return s},}});
// mengembalikan seluruh dokumen termasuk tag <html> (defaultnya salah)const clean = DOMPurify.sanitize(dirty, {WHOLE_DOCUMENT: true});// menonaktifkan perlindungan DOM Clobbering pada output (defaultnya benar, tangani dengan hati-hati, XSS kecil risiko di sini)const clean = DOMPurify.sanitize(dirty, {SANITIZE_DOM: false});// menerapkan perlindungan DOM Clobbering yang ketat melalui isolasi namespace (default salah)// bila diaktifkan, isolasi namespace properti bernama (yaitu atribut `id` dan `name`)// dari variabel JS dengan mengawalinya dengan string `user-content-`const clean = DOMPurify.sanitize( kotor, {SANITIZE_NAMED_PROPS: true});// menyimpan konten elemen ketika elemen tersebut dihapus (defaultnya adalah true)const clean = DOMPurify.sanitize(dirty, {KEEP_CONTENT: false});// merekatkan elemen seperti gaya, skrip, atau lainnya ke document.body dan mencegah perilaku browser yang tidak intuitif dalam beberapa kasus tepi (defaultnya salah)const clean = DOMPurify.sanitize(dirty, {FORCE_BODY: true} );// hapus semua elemen <a> di bawah elemen <p> yang dihapusconst clean = DOMPurify.sanitize(dirty, {FORBID_CONTENTS: ['a'], FORBID_TAGS: ['p']});// ubah tipe parser sehingga data yang sudah dibersihkan diperlakukan sebagai XML dan bukan sebagai HTML, yang merupakan defaultconst clean = DOMPurify.sanitize(dirty, {PARSER_MEDIA_TYPE: ' aplikasi/xhtml+xml'});
// gunakan mode IN_PLACE untuk membersihkan node "di tempat", yang jauh lebih cepat bergantung pada cara Anda menggunakan DOMPurifyconst dirty = document.createElement('a');dirty.setAttribute('href', 'javascript:alert(1 )');const clean = DOMPurify.sanitize(kotor, {IN_PLACE: true}); // lihat https://github.com/cure53/DOMPurify/issues/288 untuk info lebih lanjut
Ada lebih banyak contoh di sini, yang menunjukkan bagaimana Anda dapat menjalankan, menyesuaikan, dan mengonfigurasi DOMPurify agar sesuai dengan kebutuhan Anda.
Daripada meneruskan konfigurasi yang sama berulang kali ke DOMPurify.sanitize
, Anda dapat menggunakan metode DOMPurify.setConfig
. Konfigurasi Anda akan bertahan hingga panggilan berikutnya ke DOMPurify.setConfig
, atau hingga Anda memanggil DOMPurify.clearConfig
untuk menyetel ulang. Ingatlah bahwa hanya ada satu konfigurasi aktif, yang berarti setelah disetel, semua parameter konfigurasi tambahan yang diteruskan ke DOMPurify.sanitize
akan diabaikan.
DOMPurify memungkinkan Anda untuk menambah fungsinya dengan melampirkan satu atau lebih fungsi dengan metode DOMPurify.addHook
ke salah satu kait berikut:
beforeSanitizeElements
uponSanitizeElement
(Tidak ada 's' - dipanggil untuk setiap elemen)
afterSanitizeElements
beforeSanitizeAttributes
uponSanitizeAttribute
afterSanitizeAttributes
beforeSanitizeShadowDOM
uponSanitizeShadowNode
afterSanitizeShadowDOM
Ini meneruskan node DOM yang sedang diproses, bila diperlukan literal dengan node terverifikasi dan data atribut serta konfigurasi DOMPurify ke callback. Lihat demo hook MentalJS untuk melihat bagaimana API dapat digunakan dengan baik.
Contoh :
DOMPurify.addHook( 'pada SanitizeAttribute', function (currentNode, hookEvent, config) {// Melakukan sesuatu dengan node saat ini// Anda juga dapat mengubah hookEvent untuk node saat ini (yaitu menyetel hookEvent.forceKeepAttr = true)// Untuk jenis hook selain 'uponSanitizeAttribute' hookEvent sama dengan null });
Pilihan | Sejak | Catatan |
---|---|---|
SAFE_FOR_JQUERY | 2.1.0 | Tidak diperlukan penggantian. |
Kami saat ini menggunakan Github Actions yang dikombinasikan dengan BrowserStack. Ini memberi kami kemungkinan untuk mengonfirmasi setiap komitmen bahwa semuanya berjalan sesuai rencana di semua browser yang didukung. Lihat log build di sini: https://github.com/cure53/DOMPurify/actions
Anda selanjutnya dapat menjalankan pengujian lokal dengan menjalankan npm test
. Pengujian berfungsi dengan baik dengan Node.js v0.6.2 dan [email protected].
Semua komitmen yang relevan akan ditandatangani dengan kunci 0x24BB6BF4
untuk keamanan tambahan (sejak 8 April 2016).
npm i
) Kami mendukung npm
secara resmi. Alur kerja GitHub Actions dikonfigurasikan untuk menginstal dependensi menggunakan npm
. Saat menggunakan versi npm
yang tidak digunakan lagi, kami tidak dapat sepenuhnya memastikan versi dependensi yang diinstal yang mungkin menyebabkan masalah yang tidak terduga.
Kami mengandalkan skrip run npm untuk berintegrasi dengan infrastruktur perkakas kami. Kami menggunakan ESLint sebagai pre-commit hook untuk memastikan konsistensi kode. Selain itu, untuk memudahkan pemformatan kami menggunakan prettier saat membangun aset /dist
terjadi melalui rollup
.
Ini adalah skrip npm kami:
npm run dev
untuk mulai membangun sambil mengamati sumber perubahan
npm run test
untuk menjalankan rangkaian pengujian kami melalui jsdom dan karma
test:jsdom
untuk hanya menjalankan tes melalui jsdom
test:karma
untuk hanya menjalankan tes melalui karma
npm run lint
untuk lint sumber menggunakan ESLint (melalui xo)
npm run format
untuk memformat sumber kami menggunakan lebih cantik untuk memudahkan melewati ESLint
npm run build
untuk membangun aset distribusi kami yang diperkecil dan tidak diperkecil sebagai modul UMD
npm run build:umd
untuk hanya membuat modul UMD yang tidak diminifikasi
npm run build:umd:min
untuk hanya membuat modul UMD yang diperkecil
Catatan: semua skrip yang dijalankan dipicu melalui npm run <script>
.
Ada lebih banyak skrip npm tetapi sebagian besar ditujukan untuk berintegrasi dengan CI atau dimaksudkan sebagai "pribadi" misalnya untuk mengubah file distribusi build dengan setiap penerapan.
Kami bu