4 puan yazan GN⁺ 2024-09-02 | 1 yorum | WhatsApp'ta paylaş
  • Web panosu, bir kez kopyalanan veriyi bile birden çok MIME temsiliyle birlikte saklayarak, her uygulamanın yalnızca ihtiyaç duyduğu biçimi seçip yapıştırabilmesini sağlar
  • async Clipboard API, ağırlıklı olarak text/plain, text/html, image/png ile sınırlıdır; application/json gibi özel türler güvenlik nedeniyle yazma sırasında reddedilir
  • Eski Clipboard Events API, rastgele tür dizeleriyle çalışabilir; ancak gerçek sistem panosu yalnızca güvenilir kullanıcı etkinlikleri içinde değiştirilebilir
  • Google Docs, execCommand("copy") ile güvenilir bir copy etkinliği oluşturur; Figma ise tarayıcı ile yerel uygulama arasındaki kopyalamayı yönetmek için özel verileri base64 HTML özniteliklerine koyar
  • Web Custom Formats, "web " önekiyle async Clipboard API’de özel türlerin önünü açar; ancak Chromium tabanlı tarayıcılar ve güncellenmiş yerel uygulamalar gerekir

Web panosunun temel modeli

  • Pano, tek bir kopyalama işlemi için birden çok temsili (representation) MIME türleriyle birlikte saklayabilir
    • text/plain: düz metin
    • text/html: HTML
    • image/png: PNG görüntüsü
  • Google Docs, bağlantılar, yazı boyutu ve renk gibi biçimlendirmeyi korumak için text/html temsilini okur
  • VS Code gibi yalnızca kaynak metne ihtiyaç duyan uygulamalar için text/plain temsilini okumak yeterlidir

async Clipboard API’nin tür sınırlaması

  • navigator.clipboard.read(), pano öğesinin types değerlerini kontrol ettikten sonra getType("text/html") gibi belirli bir temsili okur
  • navigator.clipboard.write(), MIME türünü anahtar olarak kullanan bir ClipboardItem içine birden çok Blob koyup bunları tek seferde yazabilir
  • application/json bir ClipboardItem olarak yazılmaya çalışıldığında Type application/json not supported on write istisnası oluşur
  • W3C Clipboard şartnamesi, text/plain, text/html, image/png dışındaki türlerin write sırasında reddedilmesini öngörür
  • application/json, 2012’den 2021’e kadar zorunlu veri türleri listesinde yer alıyordu; ancak w3c/clipboard-apis#155 ile kaldırıldı
    • Değişiklikten önce zorunlu veri türleri okuma için 16, yazma için 8 adetti
    • Tarayıcılar güvenlik kaygıları nedeniyle birçok zorunlu türü desteklemediği için liste küçültüldü
  • Şartname, güvenilmeyen betiklerin yerel yazılım açıklarını tetikleyebilecek verileri panoya koyabileceği konusunda uyarır ve bu nedenle izin verilen türlerin sınırlandırıldığını belirtir

Clipboard Events API ve isTrusted

  • ClipboardEvent, copy, cut, paste etkinliklerinde oluşur ve clipboardData özelliği üzerinden bir DataTransfer nesnesi sağlar
  • copy etkinliğinde e.clipboardData.setData("text/plain", "..."), setData("text/html", "...") ile veri yazılabilir
  • paste etkinliğinde e.clipboardData.getData("text/html") ile HTML temsili okunabilir
  • clipboardData.setData("application/json", json) istisna fırlatmaz; paste işleyicisinde de application/json türü ve JSON dizgesi görülebilir
  • clipboardData, async Clipboard API’den çok daha eski bir arayüzdür
    • async Clipboard API, 2017’de şartnameye eklendi
    • clipboardData, setData, getData 2006 tarihli W3C taslağında zaten yer alıyordu
    • Bu taslak, Internet Explorer’da uygulanmış işlevleri büyük ölçüde yansıtıyordu
    • Internet Explorer 4, 1997’de yayımlandığı için clipboardData arayüzünün yazının kaleme alındığı an itibarıyla en az 26 yıllık bir özellik olduğu söylenebilir
  • MIME türleri 2011 şartnamesinden itibaren geldi; ancak setData() için tür argümanı olarak herhangi bir dizge kullanabilme özelliği bugün de korunuyor
  • Event.isTrusted, etkinlik yalnızca kullanıcı aracısı tarafından oluşturulduğunda true olan salt okunur bir özelliktir
    • Kullanıcının Command+C’ye basmasıyla oluşan copy etkinliğinde isTrusted değeri true olur
    • dispatchEvent() ile oluşturulan sentetik etkinliklerde isTrusted değeri false olur
  • Sentetik copy/cut etkinlikleri sistem panosunu değiştiremez; sentetik paste etkinlikleri de gerçek sistem panosu verisine erişemez
  • Bu nedenle Clipboard Events API rastgele türlerle çalışabilse de gerçek panoyla etkileşim, kullanıcı aracısının oluşturduğu copy/paste etkinlik işleyicileriyle sınırlıdır

Copy düğmesinde özel tür yazma

  • Google Docs’un sağ tık menüsündeki Copy düğmesi panoya üç temsil yazar
    • text/plain
    • text/html
    • application/x-vnd.google-docs-document-slice-clip+wrapped
  • Üçüncü temsil, JSON verisi taşıyan özel bir türdür ve yalnızca async Clipboard API ile yazılamaz
  • Google Docs, Copy düğmesine tıklandığında document.execCommand("copy") çağırır
  • execCommand("copy"), kullanıcı kopyalama komutunu çalıştırmış gibi programatik olarak güvenilir bir copy etkinliği oluşturabilir
  • Safari’de execCommand("copy") çağrısının copy etkinliği oluşturabilmesi için etkin bir seçim alanı gerekir
    • Boş olmayan bir input’u DOM’a ekleyip seçtikten sonra execCommand("copy") çağırıp kaldırarak seçim alanı oluşturulabilir

Paste düğmesinde tarayıcı ve OS farkları

  • Google Docs’un Paste düğmesi macOS’te eklenti kurulmasını isterken, Windows dizüstü bilgisayarda çalışıyordu
  • Paste komutu desteği document.queryCommandSupported("paste") ile kontrol edilebilir
    • macOS’te Chrome ve Firefox false, Safari true döndürür
    • Windows’ta Chrome ve Edge true, Firefox false döndürür
  • Safari, yapıştırma işlemini onaylatan bir istem göstererek web sitesinin panoyu okuduğunu açıkça gösterir
  • Chrome’un Windows’ta execCommand("paste")e izin verip macOS’te izin vermemesinin nedeni doğrulanmamıştır
  • Google Docs, execCommand("paste") kullanılamadığında async Clipboard API’ye geri düşmez
    • async Clipboard API ile application/x-vnd.google-[...] temsili okunamaz
    • HTML temsilinde dahili ID bulunur

Figma’nın HTML tabanlı kopyalama-yapıştırması

  • Figma’nın Copy düğmesi panoya text/plain ve text/html olmak üzere iki temsil yazar
  • HTML temsilinde iki boş span vardır ve bunların her biri data-metadata, data-buffer özniteliklerine sahiptir
  • data-metadata, base64 ile kodlanmış bir JSON dizgesidir; kodu çözüldüğünde fileKey, pasteID, dataType gibi değerler çıkar
  • data-buffer, yalnızca boş bir frame kopyalansa bile yaklaşık 26.000 karakterdir ve uzunluğunun kopyalanan içerik miktarına göre doğrusal arttığı görülür
  • data-buffer base64’ten çözüldüğünde fig-kiwi ile başlayan ikili veri ortaya çıkar; bu Kiwi message format biçimidir
    • Kiwi, Figma’nın kurucu ortaklarından ve eski CTO’su Evan Wallace tarafından oluşturulmuş bir biçimdir
    • .fig dosyalarının kodlanmasında kullanılır
  • Evan Wallace’ın yayımladığı .fig file parser kullanılarak data-buffer bir .fig dosyasına dönüştürülüp incelenebilir
  • Figma, küçük bir Figma dosyası oluşturur, bunu base64 ile kodlar ve boş HTML span öğesinin data-buffer özniteliğine koyarak panoda saklar

HTML temsili kullanmanın nedeni

  • Windows, macOS ve Linux, panoya veri yazmak için birbirinden farklı OS biçimleri sağlar
    • Windows, HTML için CF_HTML sağlar
    • macOS, NSPasteboard.PasteboardType.html sağlar
  • Düz metin, HTML ve PNG görüntüleri birçok OS’te standart biçimlere eşlenebilir
  • application/foo-bar gibi rastgele türler, OS panosunun ortak biçimleriyle pek uyumlu değildir
  • Tarayıcılar bu tür özel temsilleri OS’in ortak pano biçimlerine yazmaz; tarayıcıya özgü özel pano biçimlerinin içinde saklar
    • Bunun sonucunda özel türler tarayıcı sekmeleri arasında kopyalanıp yapıştırılabilir
    • Uygulamalar arasında kopyalanıp yapıştırılamaz
  • text/html kullanıldığında OS’in ortak pano biçimine eşlenir ve diğer uygulamalar tarafından daha kolay okunur
  • Figma, text/html kullanarak tarayıcıdaki figma.com ile yerel Figma uygulaması arasında öğelerin kopyalanıp yapıştırılabilmesini sağlar

Tarayıcıya göre özel veri saklama biçimleri

  • macOS’te bir copy etkinliği içinde text/plain, text/html, application/json, foo bar baz yazılıp Pasteboard Viewer ile kontrol edildiğinde, tarayıcıların saklama biçimleri farklıdır
  • Chrome, Pasteboard’a dört öğe ekler
    • public.html: HTML temsili
    • public.utf8-plain-text: düz metin temsili
    • org.chromium.web-custom-data: özel temsil
    • org.chromium.source-url: kopyalamanın yapıldığı web sayfasının URL’si
  • Firefox da public.html, public.utf8-plain-text oluşturur; ancak özel veriyi org.mozilla.custom-clipdata içine yazar
    • Chrome’un aksine kaynak URL’yi saklamaz
  • Safari de public.html, public.utf8-plain-text oluşturur ve özel veriyi com.apple.WebKit.custom-pasteboard-data içine yazar
    • Bu öğenin içinde düz metin ve HTML dahil tüm temsil listesi ile kaynak URL de saklanır
  • Safari, yalnızca kaynak URL’nin alan adı aynı olduğunda tarayıcı sekmeleri arasında özel tür kopyalama-yapıştırmaya izin verir
    • Chrome ve Firefox’ta aynı kısıtlama görülmez

Raw Clipboard Access ve Web Custom Formats

  • Raw Clipboard Access, 2019’da önerilen bir API’ydi ve web uygulamalarına yerel OS panosuna ham okuma-yazma erişimi sağlamayı amaçlıyordu
  • Raw Clipboard Access, web uygulamalarının az sayıda biçimle sınırlı olması nedeniyle Figma ve Photopea’nın çoğu görüntü biçimiyle birlikte çalışmakta zorlanması sorununu ele alıyordu
  • Bu öneri, yerel uygulamalarda uzaktan kod çalıştırma gibi güvenlik kaygıları nedeniyle ilerlemedi
  • Web Custom Formats, async Clipboard API’de özel türler yazmaya yönelik bir öneridir; Chromium bunu 2022’de uygulamaya aldı
  • Web Custom Formats, MIME türünün başına "web " eklenerek kullanılır
    • Örnek: web application/json
    • Okurken de async Clipboard API’nin read() ve getType("web application/json") kullanılır
  • Web Custom Formats, yerel OS panosuna iki tür veri yazar
    • Veri türleri ile pano öğesi adları arasındaki eşleme
    • Her veri türü için pano öğesi
  • macOS’te eşleme org.w3.web-custom-format.map içinde saklanır
    • Örnek: "application/json": "org.w3.web-custom-format.type-0"
  • org.w3.web-custom-format.type-[index] öğelerinde Blob’un ham verisi bulunur
  • Bu yöntem, web uygulamalarının istedikleri OS pano biçimine doğrudan ham veri yazmasını engelleyerek Raw Clipboard Access’in güvenlik sorunlarından kaçınır
  • Buna karşılık, eski yerel uygulamalarla güncelleme olmadan birlikte çalışmak hedeflenmez
    • Yerel uygulamaların Web Custom Formats biçimini okuyacak şekilde güncellenmesi gerekir
  • Web Custom Formats, 2022’den beri Chromium tabanlı tarayıcılarda kullanılabilir; ancak diğer tarayıcılar henüz uygulamamıştır

unsanitized seçeneği

  • async Clipboard API ile pano okunurken tarayıcı veriyi temizleyebilir
    • HTML içinden tehlikeli olabilecek script etiketlerini kaldırabilir
    • zip bomb saldırılarından kaçınmak için PNG görüntüsünü yeniden kodlayabilir
  • read() içindeki unsanitized seçeneği, temizlenmemiş verinin istenebilmesini sağlar
  • Bu seçenek şu anda yalnızca Chromium tabanlı tarayıcılarda desteklenir
    • 2023 sonlarında eklendi
    • Diğer tarayıcılar ileride destekleyebilir; ancak Safari için bunun pek olası görünmediğini belirten geri bildirimler vardır

Gerçekçi seçenekler

  • Tüm tarayıcılarda iyi çalışan bir özel pano türü yazma yöntemi henüz yok
  • Figma’nın yaptığı gibi base64 dizgesini HTML temsili içine koymak kaba bir yöntem olsa da Clipboard API’nin çeşitli kısıtlarını aşarak özel veriyi pano üzerinden aktarabilir
  • Web Custom Formats, özel türleri daha güvenli ve pratik biçimde kullanmaya yönelik bir yol sunar; ancak başlıca tarayıcıların genelinde uygulanması gerekir

1 yorum

 
GN⁺ 2024-09-02
Hacker News yorumları
  • Güzel yazı. Mac’te Firefox ile Google Docs’a biçimlendirmeyi koruyarak/biçimlendirmesiz yapıştırma işleminin neden düzgün çalışmadığını anladım.
    Google’ın panoya kendi içerik biçimini koymak için kullanımdan kaldırılmış bir API kullanıyor olması ilginç.

    • Bir gün Google web’ini resmi web’in bir fork’u olarak ilan etmemiz gerekebilir.
  • Özel uygulama verilerini panoya göndermenin en güvenilir yolu, Figma’nın yaptığı gibi veriyi HTML’in içine gömmek gibi görünüyor.
    Alıcı uygulama desteklemediğinde HTML mesajıyla başarısızlık davranışını bile tanımlayabilmek de bir avantaj.

  • WordPress de bu meseleye dokunuyor. Düzenleyici modunda birden çok paragrafı kesip yapıştırırsanız işler epey bozulabilir.
    Muhtemelen paragraflar aslında birbirinden farklı DIV alanları olduğu ve farklı kontrol mantıkları ile efektlerin altında bulunduğu içindir.
    Ayrıca makine, benim ASCII sandığım şeyi UTF-8’e ya da ISO Latin-1’e yükseltip Clippy gibi “tırnak işaretlerini daha güzel görünenlerle değiştirdim, sonra teşekkür edersin” tarzı şeyler yapıyor; bunu hiç istemedim. this' isteseydim 'this' yazmazdım.

  • Eskiden öğrenciyken JavaScript kullanıcı izni olmadan panoyu okuyabiliyordu ve getpasted adlı bir web sitesi yapmıştım.
    Panoyu otomatik olarak yapıştırıp herkese açık bir veritabanına yükleyen bir siteydi; doğal olarak bundan hoşlanmayanlar da oldu.
    Yine de panonun her an okunabildiğini gösteren bir proje olarak fena değildi.

    • Windows 11’de varsayılan olarak Clipboard History / Cloud Clipboard üzerinden tüm pano verilerinin Microsoft sunucularına gönderildiğini öğrenince insanlar şaşıracaktır.
  • Pasteboard Manager[0]’ın geliştiricisi Sindre Sorhus, Actions[1] kısayol kitaplığını ve çeşitli iPhone/Mac uygulamalarını da yapan kişi. HN’de var mı bilmiyorum.
    0. https://apps.apple.com/us/app/pasteboard-viewer/id1499215709

    1. https://apps.apple.com/us/app/actions/id1586435171
  • Kapsam ve derinlik kombinasyonu özellikle iyi. Sistem ve tarayıcı bazlı farkları ele alırken tuzakları ve geçici çözümleri de birlikte açıklıyor.

    • Yazıda aşırı ayrıntıları ve yan konuları azaltmaya çalıştım. Yazı uzun sayılır ama bu sefer dengeyi iyi kurmuşum gibi göründüğü için sevindim.
  • Tarayıcıdan “özel” verileri alma konusuyla ilgili olarak, bankamın web uygulaması girişte makine adım olan aluminium’u gösterip iki faktörlü doğrulama istedi.
    Bunu nasıl öğrendi bilmiyorum. Mobilden girince iki faktörlü doğrulama kodunu içeren SMS’i de görebiliyor ve otomatik yapıştırabiliyordu. Pixel+Chrome veya Linux+Chrome ortamıydı.

    • İki faktörlü doğrulama kodu muhtemelen bir Chrome özelliği olabilir. Safari de SMS doğrulama kodlarını otomatik tamamlama önerisi olarak gösteriyor; Android’de Chrome’un bunu doğrudan otomatik girebileceğini düşünüyorum.
      Makine adı daha zor. Bankaya bu bilgiyi kullanıcı adı gibi bir biçimde gerçekten verip vermediğini kontrol etmek gerekir. Hangi banka olduğunu da merak ettim.
  • Bu yazı, web uygulamalarının neden yerel uygulamalar kadar iyi olamayacağını iyi gösteriyor.
    Web uygulamaları her zaman “güvenilmeyen” kod olduğu için yerel makinedeki kaynaklara erişimleri keyfi ve yapay biçimde kısıtlanır.

    • Varsayılan olarak güvenmemek bir özelliktir. Sürekli tetikte olan, çok eğitimli bir güvenlik uzmanı değilseniz kullanıcının kendini koruması zordur.
      Artık script kiddie’lerin ortalıkta dolaştığı erken internet dönemi de değil, yalnızca meraklıların kullandığı bir alan da değil. Devlet bağlantılı grupların nükleer programlarını finanse etmek için kritik altyapıya fidye yazılımı saldırıları düzenlediği bir çağdayız. Yerel makinedeki keyfi kaynak erişimi tam da bu tür şeyleri mümkün kılar.
      Modern tarayıcılardaki web uygulamaları doğal olarak daha güçlü bir sandbox içinde çalışır; ancak modern işletim sistemlerinde yerel uygulamalar da güvenilmeyen hedefler olarak ele alınır. Yeni bir uygulama çalıştırdığınızda, yalıtılmış uygulama veri dizininin dışına erişmeden önce bir onay penceresi çıkar.
  • Bu arada MacBook’ta uyarı çıkaran Chrome eklentisinin hangisi olduğunu merak ediyorum.