- Clipboard web menyimpan data yang sudah disalin sekali dalam beberapa representasi MIME sekaligus, sehingga tiap aplikasi bisa memilih hanya bentuk yang dibutuhkannya saat menempel
- async Clipboard API dibatasi terutama pada
text/plain,text/html, danimage/png, sehingga tipe kustom sepertiapplication/jsonditolak saat ditulis karena alasan keamanan - Clipboard Events API yang lebih lama dapat menangani string tipe arbitrer, tetapi clipboard sistem sebenarnya hanya berubah di dalam event pengguna tepercaya
- Google Docs membuat event copy tepercaya dengan
execCommand("copy"), sementara Figma memasukkan data kustom ke dalam atribut HTML base64 untuk menangani penyalinan antara browser dan aplikasi native - Web Custom Formats membuka tipe kustom pada async Clipboard API dengan prefiks
"web ", tetapi membutuhkan browser berbasis Chromium dan aplikasi native yang sudah diperbarui
Model dasar clipboard web
- Clipboard dapat menyimpan beberapa representasi (representation) beserta tipe MIME untuk satu operasi penyalinan
text/plain: teks biasatext/html: HTMLimage/png: gambar PNG
- Google Docs membaca representasi
text/htmluntuk mempertahankan pemformatan seperti tautan, ukuran huruf, dan warna - Aplikasi yang hanya membutuhkan teks sumber seperti VS Code cukup membaca representasi
text/plain
Batasan tipe pada async Clipboard API
navigator.clipboard.read()memeriksatypesdari item clipboard lalu membaca representasi tertentu sepertigetType("text/html")navigator.clipboard.write()dapat menulis beberapaBlobsekaligus dalamClipboardItemyang memakai tipe MIME sebagai kunci- Jika mencoba menulis
application/jsonsebagaiClipboardItem, akan muncul exceptionType application/json not supported on write - Spesifikasi W3C Clipboard mengharuskan tipe selain
text/plain,text/html, danimage/pngditolak padawrite application/jsonpernah ada dalam daftar tipe data wajib dari 2012 hingga 2021, tetapi dihapus dalam w3c/clipboard-apis#155- Sebelum perubahan, tipe data wajib berjumlah 16 untuk baca dan 8 untuk tulis
- Daftar itu dipangkas karena browser tidak mendukung banyak tipe wajib akibat kekhawatiran keamanan
- Spesifikasi memperingatkan bahwa skrip tidak tepercaya dapat memasukkan data ke clipboard yang memicu kerentanan perangkat lunak lokal, sehingga tipe yang diizinkan dibatasi
Clipboard Events API dan isTrusted
ClipboardEventterjadi pada event copy, cut, dan paste, serta menyediakan objekDataTransfermelalui properticlipboardData- Pada event copy, data dapat ditulis dengan
e.clipboardData.setData("text/plain", "...")dansetData("text/html", "...") - Pada event paste, representasi HTML dapat dibaca dengan
e.clipboardData.getData("text/html") clipboardData.setData("application/json", json)tidak melempar exception, dan handler paste juga dapat melihat tipeapplication/jsonbeserta string JSON-nyaclipboardDataadalah antarmuka yang jauh lebih tua daripada async Clipboard API- async Clipboard API ditambahkan ke spesifikasi pada 2017
clipboardData,setData, dangetDatasudah muncul dalam draf W3C tahun 2006- Draf tersebut banyak merefleksikan fitur yang diimplementasikan di Internet Explorer
- Karena Internet Explorer 4 dirilis pada 1997, antarmuka
clipboardDatadapat dianggap berusia setidaknya 26 tahun pada saat artikel ditulis
- Sejak spesifikasi 2011, tipe MIME mulai masuk, tetapi sifat bahwa argumen tipe pada
setData()dapat berisi string apa pun masih dipertahankan hingga sekarang Event.isTrustedadalah properti read-only yang bernilaitruehanya ketika event dibuat oleh user agent- Event copy ketika pengguna menekan Command+C memiliki
isTrustedbernilaitrue - Event sintetis yang dibuat dengan
dispatchEvent()memilikiisTrustedbernilaifalse
- Event copy ketika pengguna menekan Command+C memiliki
- Event copy/cut sintetis tidak dapat mengubah clipboard sistem, dan event paste sintetis tidak dapat mengakses data clipboard sistem yang sebenarnya
- Karena itu, Clipboard Events API dapat menangani tipe arbitrer, tetapi interaksi dengan clipboard sebenarnya dibatasi pada handler event copy/paste yang dibuat oleh user agent
Menulis tipe kustom dari tombol Copy
- Tombol Copy pada menu klik kanan Google Docs menulis tiga representasi ke clipboard
text/plaintext/htmlapplication/x-vnd.google-docs-document-slice-clip+wrapped
- Representasi ketiga adalah tipe kustom berisi data JSON, dan tidak dapat ditulis hanya dengan async Clipboard API
- Google Docs memanggil
document.execCommand("copy")saat tombol Copy diklik execCommand("copy")dapat secara programatik memunculkan event copy tepercaya seolah pengguna menjalankan perintah salin- Di Safari,
execCommand("copy")membutuhkan area seleksi aktif agar event copy muncul- Area seleksi dapat dibuat dengan menambahkan input yang tidak kosong ke DOM, memilihnya, lalu memanggil
execCommand("copy")dan menghapusnya
- Area seleksi dapat dibuat dengan menambahkan input yang tidak kosong ke DOM, memilihnya, lalu memanggil
Perbedaan browser dan OS pada tombol Paste
- Tombol Paste di Google Docs meminta pemasangan ekstensi di macOS, tetapi berfungsi di laptop Windows
- Dukungan perintah paste dapat diperiksa dengan
document.queryCommandSupported("paste")- Di macOS, Chrome dan Firefox bernilai
false, Safari bernilaitrue - Di Windows, Chrome dan Edge bernilai
true, Firefox bernilaifalse
- Di macOS, Chrome dan Firefox bernilai
- Safari menampilkan prompt untuk mengonfirmasi aksi paste, sehingga jelas bahwa situs web membaca clipboard
- Alasan Chrome mengizinkan
execCommand("paste")di Windows tetapi tidak di macOS belum terkonfirmasi - Google Docs tidak fallback ke async Clipboard API saat
execCommand("paste")tidak dapat digunakan- async Clipboard API tidak dapat membaca representasi
application/x-vnd.google-[...] - Representasi HTML berisi ID internal
- async Clipboard API tidak dapat membaca representasi
Copy-paste berbasis HTML di Figma
- Tombol Copy Figma menulis dua representasi ke clipboard:
text/plaindantext/html - Representasi HTML berisi dua
spankosong, masing-masing memiliki atributdata-metadatadandata-buffer data-metadataadalah string JSON yang di-encode base64; setelah di-decode, muncul nilai sepertifileKey,pasteID, dandataTypedata-bufferberukuran sekitar 26.000 karakter bahkan saat hanya menyalin frame kosong, dan panjangnya tampak bertambah secara linear sesuai jumlah konten yang disalin- Jika
data-bufferdi-decode dari base64, muncul data biner yang diawalifig-kiwi; ini adalah Kiwi message format- Kiwi adalah format yang dibuat oleh Evan Wallace, salah satu pendiri Figma dan mantan CTO-nya
- Digunakan untuk encoding file
.fig
- Dengan memakai parser file
.figyang dipublikasikan Evan Wallace,data-bufferdapat dikonversi menjadi file.figuntuk diperiksa - Figma membuat file Figma kecil, meng-encode-nya ke base64, lalu memasukkannya ke atribut
data-bufferpadaspanHTML kosong untuk disimpan di clipboard
Mengapa memakai representasi HTML
- Windows, macOS, dan Linux menyediakan format OS yang berbeda untuk menulis data ke clipboard
- Windows menyediakan
CF_HTMLuntuk HTML - macOS menyediakan
NSPasteboard.PasteboardType.html
- Windows menyediakan
- Teks biasa, HTML, dan gambar PNG dapat dipetakan ke format standar di berbagai OS
- Tipe arbitrer seperti
application/foo-bartidak cocok dengan format umum clipboard OS - Browser tidak menulis representasi kustom seperti ini ke format clipboard umum milik OS, melainkan menyimpannya di dalam format clipboard kustom per browser
- Akibatnya, tipe kustom dapat di-copy-paste antar-tab browser
- Namun tidak dapat di-copy-paste antar-aplikasi
- Dengan memakai
text/html, data dipetakan ke format clipboard umum OS sehingga lebih mudah dibaca aplikasi lain - Figma memakai
text/htmlagar elemen dapat di-copy-paste antarafigma.comdi browser dan aplikasi Figma native
Cara tiap browser menyimpan data kustom
- Di macOS, jika
text/plain,text/html,application/json, danfoo bar bazditulis dalam event copy lalu diperiksa dengan Pasteboard Viewer, cara penyimpanannya berbeda di tiap browser - Chrome menambahkan empat item ke Pasteboard
public.html: representasi HTMLpublic.utf8-plain-text: representasi teks biasaorg.chromium.web-custom-data: representasi kustomorg.chromium.source-url: URL halaman web tempat penyalinan dilakukan
- Firefox juga membuat
public.htmldanpublic.utf8-plain-text, tetapi menulis data kustom keorg.mozilla.custom-clipdata- Berbeda dari Chrome, Firefox tidak menyimpan source URL
- Safari juga membuat
public.htmldanpublic.utf8-plain-text, serta menulis data kustom kecom.apple.WebKit.custom-pasteboard-data- Di dalam item ini, Safari juga menyimpan daftar seluruh representasi termasuk teks biasa dan HTML, serta source URL
- Safari mengizinkan copy-paste tipe kustom antar-tab browser hanya jika domain source URL sama
- Di Chrome dan Firefox, batasan yang sama tidak terlihat
Raw Clipboard Access dan Web Custom Formats
- Raw Clipboard Access adalah API yang diusulkan pada 2019 untuk memberi aplikasi web akses baca-tulis mentah ke clipboard OS native
- Raw Clipboard Access menangani masalah bahwa aplikasi web dibatasi pada sedikit format, sehingga Figma dan Photopea sulit berinteroperasi dengan sebagian besar format gambar
- Proposal ini tidak berlanjut lebih jauh karena kekhawatiran keamanan seperti eksekusi kode jarak jauh pada aplikasi native
- Web Custom Formats adalah proposal untuk memakai tipe kustom di async Clipboard API, dan Chromium mengimplementasikannya pada 2022
- Web Custom Formats digunakan dengan menambahkan
"web "di depan tipe MIME- Contoh:
web application/json - Saat membaca, gunakan juga
read()dari async Clipboard API dangetType("web application/json")
- Contoh:
- Web Custom Formats menulis dua jenis data ke clipboard OS native
- Pemetaan antara tipe data dan nama item clipboard
- Item clipboard untuk tiap tipe data
- Di macOS, pemetaan disimpan di
org.w3.web-custom-format.map- Contoh:
"application/json": "org.w3.web-custom-format.type-0"
- Contoh:
- Item
org.w3.web-custom-format.type-[index]berisi data mentah dari Blob - Cara ini menghindari masalah keamanan Raw Clipboard Access dengan mencegah aplikasi web menulis data mentah langsung ke format clipboard OS yang diinginkannya
- Sebagai gantinya, interoperabilitas dengan aplikasi native lama tanpa pembaruan bukanlah tujuannya
- Aplikasi native perlu diperbarui agar membaca format Web Custom Formats
- Web Custom Formats dapat digunakan di browser berbasis Chromium sejak 2022, tetapi browser lain belum mengimplementasikannya
Opsi unsanitized
- Saat membaca clipboard dengan async Clipboard API, browser dapat menyanitasi data
- Browser dapat menghapus tag script yang berpotensi berbahaya dari HTML
- Browser dapat meng-encode ulang gambar PNG untuk menghindari serangan zip bomb
- Opsi
unsanitizedpadaread()memungkinkan permintaan data yang tidak disanitasi - Opsi ini saat ini hanya didukung di browser berbasis Chromium
- Ditambahkan pada akhir 2023
- Browser lain dapat mendukungnya di masa mendatang, tetapi ada umpan balik bahwa Safari tampaknya kecil kemungkinannya
Pilihan realistis
- Saat ini belum ada cara menulis tipe clipboard kustom yang bekerja baik di semua browser
- Cara seperti Figma, yaitu memasukkan string base64 ke dalam representasi HTML, memang kasar, tetapi dapat meneruskan data kustom melalui clipboard dengan melewati berbagai batasan Clipboard API
- Web Custom Formats menyediakan arah yang lebih aman dan praktis untuk memakai tipe kustom, tetapi perlu diimplementasikan di seluruh browser utama
1 komentar
Pendapat Hacker News
Artikel yang bagus. Saya jadi paham kenapa tempel dengan/tanpa format di Google Docs pada Firefox di Mac sering tidak berjalan dengan baik.
Menarik bahwa Google memakai API yang sudah ditinggalkan untuk mencoba memasukkan format kontennya sendiri ke clipboard.
Cara paling andal untuk mengirim data aplikasi kustom ke clipboard tampaknya adalah menyematkan data di dalam HTML, seperti Figma.
Keuntungannya, ketika aplikasi penerima tidak mendukungnya, perilaku kegagalan pun bisa didefinisikan lewat pesan HTML.
WordPress juga menyentuh masalah ini. Jika memotong dan menempel beberapa paragraf dalam mode editor, hasilnya bisa rusak parah.
Mungkin karena paragraf-paragraf itu sebenarnya berada di area DIV yang berbeda-beda, serta berada di bawah logika kontrol dan efek yang berbeda.
Selain itu, mesin menaikkan sesuatu yang saya kira ASCII menjadi UTF-8 atau ISO Latin-1, lalu bertindak seperti Clippy: “Saya sudah membuat tanda kutipnya terlihat lebih bagus, nanti berterima kasihlah.” Padahal saya tidak pernah menginginkannya. Kalau saya menginginkan `this', saya tidak akan mengetik 'this'.
Dulu ketika masih mahasiswa, JavaScript bisa membaca clipboard tanpa persetujuan pengguna, dan saya membuat situs web bernama getpasted.
Situs itu secara otomatis menempelkan isi clipboard dan mengunggahnya ke basis data publik, dan tentu saja ada orang yang tidak menyukainya.
Meski begitu, sebagai proyek untuk menunjukkan bahwa clipboard bisa dibaca kapan saja, itu cukup baik.
Sindre Sorhus, pembuat Pasteboard Manager[0], juga membuat pustaka shortcut Actions[1] serta beberapa aplikasi iPhone dan Mac. Saya tidak tahu apakah dia ada di HN.
0. https://apps.apple.com/us/app/pasteboard-viewer/id1499215709
https://www.npmjs.com/~sindresorhus
Kombinasi cakupan dan kedalamannya sangat bagus. Artikel ini membahas perbedaan antar sistem dan browser, sambil juga menjelaskan jebakan dan cara mengatasinya.
Terkait pembahasan tentang mengambil data “privat” dari browser, webapp bank saya saat login menampilkan hostname saya, aluminium, dan meminta autentikasi dua faktor.
Saya tidak tahu bagaimana mereka mengetahuinya. Saat mengakses dari ponsel, aplikasi itu juga bisa melihat SMS berisi kode autentikasi dua faktor dan menempelkannya otomatis. Lingkungannya Pixel+Chrome atau Linux+Chrome.
Hostname lebih sulit. Perlu dipastikan apakah Anda benar-benar tidak pernah memberikan informasi itu ke bank dalam bentuk seperti username. Saya juga penasaran bank mana itu.
Artikel ini menunjukkan dengan baik mengapa webapp tidak bisa menjadi sebagus aplikasi native.
Webapp selalu berupa kode yang “tidak tepercaya”, sehingga akses ke resource mesin lokal dibatasi secara arbitrer dan artifisial.
Sekarang bukan lagi era awal internet ketika script kiddie merajalela, dan juga bukan ruang yang hanya dipakai para geek. Ini era ketika organisasi yang terkait pemerintah melakukan serangan ransomware terhadap infrastruktur penting untuk mendanai program nuklir. Akses sembarang ke resource mesin lokal adalah hal yang memungkinkan kejadian seperti itu.
Webapp di browser modern secara alami berada dalam sandbox yang lebih kuat, tetapi di sistem operasi modern aplikasi native pun diperlakukan sebagai pihak yang tidak tepercaya. Saat menjalankan aplikasi baru, dialog konfirmasi akan muncul sebelum aplikasi itu mengakses sesuatu di luar direktori data aplikasi yang terisolasi.
Ngomong-ngomong, saya penasaran ekstensi Chrome apa yang memunculkan peringatan di MacBook itu.