Async Clipboard API में सैनिटाइज़ नहीं किया गया एचटीएमएल

Chrome 120 में, एसिंक्रोनस क्लिपबोर्ड में unsanitized का एक नया विकल्प उपलब्ध है एपीआई. यह विकल्प HTML के साथ विशेष परिस्थितियों में सहायता कर सकता है, जहां पर आपको क्लिपबोर्ड की सामग्री ठीक उसी तरह पेस्ट करें जैसे वह कॉपी करते समय थी. इसका मतलब है कि सैनिटाइज़ेशन के किसी ऐसे तरीके के बिना जो आम तौर पर ब्राउज़र में होता है—और अच्छी वजहों से—लागू करें. इस गाइड में इसे इस्तेमाल करने का तरीका जानें.

Google Analytics 360 के साथ काम करते समय एक साथ काम करने वाला क्लिपबोर्ड एपीआई, ज़्यादातर मामलों में, डेवलपर को डेवलपरों को यह चिंता करने की ज़रूरत नहीं होती कि और वे क्लिपबोर्ड पर मौजूद कॉन्टेंट को समझ सकते हैं और मान सकते हैं कि वे क्लिपबोर्ड (कॉपी) और वे दोनों एक ही तरीके से डेटा पढ़ते हैं क्लिपबोर्ड पर कॉपी करें (चिपकाएं).

टेक्स्ट के मामले में यह बात बिलकुल सही है. DevTools में इस कोड को चिपकाकर देखें कंसोल में जाकर, पेज पर तुरंत फिर से फ़ोकस करें. (setTimeout() ज़रूरी है इसलिए आपके पास पेज पर फ़ोकस करने के लिए काफ़ी समय होता है, जो कि एक साथ काम नहीं करने वाली प्रोसेस (एसिंक) क्लिपबोर्ड एपीआई.) जैसा कि आपको दिख रहा है, इनपुट पूरी तरह से आउटपुट जैसा ही है.

setTimeout(async () => {
  const input = 'Hello';
  await navigator.clipboard.writeText(input);
  const output = await navigator.clipboard.readText();
  console.log(input, output, input === output);
  // Logs "Hello Hello true".
}, 3000);

इमेज के मामले में, यह थोड़ा अलग है. तथाकथित कंप्रेशन बॉम्ब हमले, ब्राउज़र PNG जैसी इमेज को फिर से कोड में बदलें, लेकिन इनपुट और आउटपुट इमेज विज़ुअल तौर पर दिखाएं बिलकुल पहले जैसा, पिक्सल प्रति पिक्सल.

setTimeout(async () => {
  const dataURL =
    'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=';
  const input = await fetch(dataURL).then((response) => response.blob());
  await navigator.clipboard.write([
    new ClipboardItem({
      [input.type]: input,
    }),
  ]);
  const [clipboardItem] = await navigator.clipboard.read();
  const output = await clipboardItem.getType(input.type);
  console.log(input.size, output.size, input.type === output.type);
  // Logs "68 161 true".
}, 3000);

हालांकि, एचटीएमएल टेक्स्ट का क्या होता है? जैसा कि आपने अनुमान लगाया होगा, HTML के साथ, हालात अलग हैं. यहां ब्राउज़र, किसी भी गड़बड़ी को रोकने के लिए एचटीएमएल कोड को साफ़ करता है चीज़ें होने से रोकना. उदाहरण के लिए, एचटीएमएल से <script> टैग को अलग करना और सीएसएस को इनलाइन करके कोड (और <meta>, <head>, और <style> जैसे दूसरे वर्शन) का इस्तेमाल करें. नीचे दिए गए उदाहरण को आज़माएं और DevTools कंसोल में इसे आज़माएं. आपको ध्यान रहे कि आउटपुट, इनपुट से काफ़ी अलग है.

setTimeout(async () => {
  const input = `<html>  
  <head>  
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  
    <meta name="ProgId" content="Excel.Sheet" />  
    <meta name="Generator" content="Microsoft Excel 15" />  
    <style>  
      body {  
        font-family: HK Grotesk;  
        background-color: var(--color-bg);  
      }  
    </style>  
  </head>  
  <body>  
    <div>hello</div>  
  </body>  
</html>`;
  const inputBlob = new Blob([input], { type: 'text/html' });
  await navigator.clipboard.write([
    new ClipboardItem({
      'text/html': inputBlob,
    }),
  ]);
  const [clipboardItem] = await navigator.clipboard.read();
  const outputBlob = await clipboardItem.getType('text/html');
  const output = await outputBlob.text();
  console.log(input, output);
}, 3000);

आम तौर पर, एचटीएमएल की सफ़ाई करना अच्छी बात है. आपको अपना डेटा सार्वजनिक नहीं करना है ज़्यादातर मामलों में, सैनिटाइज़ नहीं किए गए एचटीएमएल को अनुमति देकर सुरक्षा से जुड़ी समस्याओं को हल करने में मदद मिलती है. यह लीजिए हालांकि, ऐसी स्थितियां होती हैं जिनमें डेवलपर को अच्छी तरह से पता होता है कि वह क्या कर रहा है और जहां इन- और आउटपुट एचटीएमएल का भरोसा ऐप्लिकेशन के काम करने के तरीके को बेहतर बनाने के लिए किया जा सकता है. ऐसे में, आपके पास दो विकल्प हैं:

  1. अगर आप कॉपी करने और चिपकाने के अंत को नियंत्रित करते हैं, तो उदाहरण के लिए, अगर आप से अपने ऐप्लिकेशन के अंदर पेस्ट करना है, तो आपको Async Clipboard API के लिए वेब पर पसंद के मुताबिक बनाए गए फ़ॉर्मैट. यहां पढ़ना बंद करें और लिंक किया गया लेख देखें.
  2. अगर ऐप्लिकेशन में सिर्फ़ चिपकाने के आखिरी हिस्से को कंट्रोल किया जाता है, न कि कॉपी करने के आखिरी हिस्से को, ऐसा इसलिए हो सकता है, क्योंकि कॉपी करने की कार्रवाई किसी ऐसे नेटिव ऐप्लिकेशन में होती है जो वेब कस्टम फ़ॉर्मैट के लिए, आपको unsanitized विकल्प का इस्तेमाल करना चाहिए, इस लेख के बाकी हिस्से में बताया गया है.

सैनिटाइज़ेशन में script टैग हटाने, इनलाइन स्टाइल, और यह पक्का करना होगा कि एचटीएमएल सही तरीके से बनाया गया है. इसमें पूरी जानकारी नहीं है. साथ ही, इसमें अन्य जानकारी भी दी गई है आने वाले समय में इसके चरण जोड़े जा सकते हैं.

सैनिटाइज़ नहीं किए गए एचटीएमएल को कॉपी करें और चिपकाएं

जब एसिंक्रोनस क्लिपबोर्ड एपीआई की मदद से, एचटीएमएल को क्लिपबोर्ड पर write() (कॉपी) किया जाता है, ब्राउज़र यह पक्का करता है कि उसे किसी DOM पार्सर के ज़रिए चलाकर ठीक से बनाया गया हो और उससे मिलने वाली एचटीएमएल स्ट्रिंग को क्रम से लगाता है, लेकिन साइट पर कोई सैनिटाइज़ेशन नहीं होता है यह चरण पूरा करें. आपको कुछ भी करने की ज़रूरत नहीं है. जब आप read() HTML को क्लिपबोर्ड पर दूसरे ऐप्लिकेशन के क्लिपबोर्ड पर काम करता है और आपका वेब ऐप्लिकेशन पूरी फ़िडेलिटी का कॉन्टेंट हो और जिसे अपने कोड में सैनिटाइज़ेशन की ज़रूरत हो, आपके पास किसी प्रॉपर्टी के साथ, विकल्प ऑब्जेक्ट को read() तरीके में पास करने का विकल्प होता है unsanitized और ['text/html'] की वैल्यू. अलग से, यह ऐसा दिखेगा: navigator.clipboard.read({ unsanitized: ['text/html'] }). यहां दिया गया कोड सैंपल नीचे पहले दिखाए गए तरीके के जैसा ही है. हालांकि, इस बार unsanitized के साथ ऐसा ही है का विकल्प शामिल है. DevTools कंसोल में इसे आज़माने पर, आपको दिखेगा कि इनपुट और आउटपुट एक जैसा हो.

setTimeout(async () => {
  const input = `<html>  
  <head>  
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  
    <meta name="ProgId" content="Excel.Sheet" />  
    <meta name="Generator" content="Microsoft Excel 15" />  
    <style>  
      body {  
        font-family: HK Grotesk;  
        background-color: var(--color-bg);  
      }  
    </style>  
  </head>  
  <body>  
    <div>hello</div>  
  </body>  
</html>`;
  const inputBlob = new Blob([input], { type: 'text/html' });
  await navigator.clipboard.write([
    new ClipboardItem({
      'text/html': inputBlob,
    }),
  ]);
  const [clipboardItem] = await navigator.clipboard.read({
    unsanitized: ['text/html'],
  });
  const outputBlob = await clipboardItem.getType('text/html');
  const output = await outputBlob.text();
  console.log(input, output);
}, 3000);

ब्राउज़र समर्थन और सुविधा की पहचान

यह देखने का कोई सीधा तरीका नहीं है कि यह सुविधा काम करती है या नहीं. इसलिए, की पहचान, व्यवहार को ध्यान में रखकर की जाती है. इसलिए, निम्न उदाहरण इस तरह के फ़ंक्शन का इस्तेमाल इस बात का पता लगाने के लिए किया जाता है कि कोई <style> टैग सुरक्षित है या नहीं. सहायता दिखाता है या उसे इनलाइन किया जा रहा है. इसका मतलब है कि सहायता उपलब्ध नहीं है. ध्यान दें कि यह काम करे, इसके लिए पेज पर पहले से ही क्लिपबोर्ड इस्तेमाल किया जाना ज़रूरी है अनुमति.

const supportsUnsanitized = async () => {
  const input = `<style>p{color:red}</style><p>a`;
  const inputBlob = new Blob([input], { type: 'text/html' });
  await navigator.clipboard.write([
    new ClipboardItem({
      'text/html': inputBlob,
    }),
  ]);
  const [clipboardItem] = await navigator.clipboard.read({
    unsanitized: ['text/html],
  });
  const outputBlob = await clipboardItem.getType('text/html');
  const output = await outputBlob.text();
  return /<style>/.test(output);
};

डेमो

unsanitized विकल्प को इस्तेमाल करने के लिए, देखें Gitch पर डेमो और सोर्स कोड.

मीटिंग में सामने आए नतीजे

जैसा कि शुरुआती जानकारी में बताया गया है, ज़्यादातर डेवलपर को कभी भी परेशान होने की ज़रूरत नहीं होगी क्लिपबोर्ड सैनिटाइज़ेशन और सिर्फ़ डिफ़ॉल्ट सैनिटाइज़ेशन विकल्पों के साथ काम कर सकता है को भी डाउनलोड करता है. बहुत कम मामलों में जब डेवलपर को ध्यान रखने की ज़रूरत होती है, तो unsanitized विकल्प मौजूद है.

स्वीकार की गई

इस लेख की समीक्षा अनुपम स्निग्धा ने की है और रेचल एंड्रयू. एपीआई तय किया गया और इसे Microsoft Edge टीम ने लागू किया है.