Chrome एक्सटेंशन में eval का इस्तेमाल करना

Chrome का एक्सटेंशन सिस्टम, डिफ़ॉल्ट रूप से काफ़ी सख्त डिफ़ॉल्ट कॉन्टेंट की सुरक्षा के बारे में नीति (सीएसपी) लागू करता है. नीति से जुड़ी पाबंदियां आसान हैं: स्क्रिप्ट को लाइन से बाहर की ओर करके, addEventListener का इस्तेमाल करने के लिए JavaScript फ़ाइलों, इनलाइन इवेंट हैंडलर को बदलना ज़रूरी है, और eval() बंद किया गया. Chrome ऐप्स की नीति और भी सख्त नीति है और हम सुरक्षा से काफ़ी खुश हैं प्रॉपर्टी, जो इन नीतियों से मिलती हैं.

हालांकि, हम मानते हैं कि कई लाइब्रेरी eval() और eval जैसे निर्माणों का इस्तेमाल करती हैं, जैसे कि new Function() का इस्तेमाल परफ़ॉर्मेंस ऑप्टिमाइज़ेशन और आसानी से दिखने के लिए किया जा सकता है. टेंप्लेट बनाने वाली लाइब्रेरी ख़ास तौर पर इस स्टाइल के लागू होने की संभावना ज़्यादा होती है. वहीं कुछ (जैसे, Angular.js) CSP आउट का इस्तेमाल करते हैं बहुत सारे लोकप्रिय फ़्रेमवर्क अभी तक ऐसे तरीके से अपडेट नहीं हुए हैं जो एक्सटेंशन' eval-कम दुनिया. इसलिए, इस फ़ंक्शन के लिए सहायता टीम को हटाने से यह ज़्यादा साबित हुआ है ज़्यादा समस्याएं होती हैं.

यह दस्तावेज़ इन लाइब्रेरी को आपके प्रोजेक्ट में शामिल करने के लिए, सुरक्षित तरीके के तौर पर सैंडबॉक्सिंग के बारे में बताता है वह भी सुरक्षा से समझौता किए बिना. संक्षिप्तता के लिए, हम शुरू से अंत तक एक्सटेंशन शब्द का उपयोग करेंगे, लेकिन यह सिद्धांत समान रूप से ऐप्लिकेशन पर लागू होता है.

सैंडबॉक्स का इस्तेमाल क्यों करें?

एक्सटेंशन के अंदर eval खतरनाक है, क्योंकि इसे लागू करने वाले कोड के पास एक्सटेंशन में मौजूद सभी चीज़ों का ऐक्सेस होता है एक्सटेंशन की उच्च-अनुमति वातावरण उपलब्ध कराते हैं. ऐसे कई दमदार chrome.* API उपलब्ध हैं जो उपयोगकर्ता की सुरक्षा और निजता पर गंभीर असर डाल सकता है; डेटा को आसानी से बाहर निकाला जाना हमारी सबसे कम चिंता है. हमारा समाधान एक सैंडबॉक्स की तरह है. इसमें eval, एक्सटेंशन का डेटा या एक्सटेंशन के ज़्यादा वैल्यू वाले एपीआई का इस्तेमाल करते हैं. कोई डेटा नहीं, कोई एपीआई नहीं, कोई समस्या नहीं.

ऐसा करने के लिए, हम एक्सटेंशन पैकेज में मौजूद चुनिंदा एचटीएमएल फ़ाइलों को सैंडबॉक्स के तौर पर दिखाते हैं. जब भी कोई सैंडबॉक्स किया गया पेज लोड होता है, तो उसे यूनीक ऑरिजिन में ले जाया जाएगा और इसे अस्वीकार कर दिया जाएगा chrome.* एपीआई का ऐक्सेस. अगर हम इस सैंडबॉक्स किए गए पेज को किसी iframe के ज़रिए अपने एक्सटेंशन में लोड करते हैं, तो उसे संदेश भेज देता है, उसे उन संदेशों पर किसी तरह कार्रवाई करने देता है, और जब तक वह हमें नतीजा. इस आसान मैसेज सेवा के ज़रिए हमें वे सभी सुविधाएं मिलती हैं जिनकी ज़रूरत हमें सुरक्षित तरीके से eval की मदद से चलाने के लिए होती है हमारे एक्सटेंशन के वर्कफ़्लो में इस्तेमाल किया जा सकता है.

सैंडबॉक्स बनाना और उसका इस्तेमाल करना.

यदि आप सीधे कोड में जाना चाहते हैं, तो कृपया सैंडबॉक्सिंग नमूना एक्सटेंशन लें और बंद है. यह हैंडलबार के ऊपर बने छोटे से मैसेजिंग एपीआई का उदाहरण है आपको एक लाइब्रेरी बनानी होगी. इसमें आपको काम शुरू करने से जुड़ी हर चीज़ मिल जाएगी. उन लोगों के लिए जिन्हें आइए, उस सैंपल के बारे में यहाँ जानते हैं.

मेनिफ़ेस्ट में फ़ाइलों की सूची बनाएं

जिस फ़ाइल को सैंडबॉक्स में चलाना है उसे एक्सटेंशन मेनिफ़ेस्ट में एक sandbox प्रॉपर्टी. यह एक ज़रूरी चरण है और इसे भूलना आसान है. इसलिए, कृपया दोबारा आपकी सैंडबॉक्स फ़ाइल, मेनिफ़ेस्ट में मौजूद होती है. इस सैंपल में, हम सही तरीके से फ़ाइल को सैंडबॉक्स कर रहे हैं का नाम "sandbox.html" है. मेनिफ़ेस्ट एंट्री इस तरह दिखती है:

{
  ...,
  "sandbox": {
     "pages": ["sandbox.html"]
  },
  ...
}

सैंडबॉक्स की गई फ़ाइल लोड करें

सैंडबॉक्स की गई फ़ाइल के साथ कुछ दिलचस्प करने के लिए, हमें उसे ऐसे कॉन्टेक्स्ट में लोड करना होगा जहां तो उसे एक्सटेंशन के कोड से ठीक किया जा सकता है. यहां sandbox.html लोड कर दिया गया है एक्सटेंशन का इवेंट पेज (eventpage.html) किसी iframe के ज़रिए. eventpage.js में कोड शामिल है यह iframe को खोजकर, ब्राउज़र की कार्रवाई को क्लिक करने पर सैंडबॉक्स में एक मैसेज भेजता है पेज पर मौजूद है और उसके contentWindow पर postMessage तरीके को लागू किया जा रहा है. मैसेज एक ऑब्जेक्ट है इसमें दो प्रॉपर्टी शामिल हैं: context और command. हम जल्द ही इन दोनों के बारे में बात करेंगे.

chrome.browserAction.onClicked.addListener(function() {
 var iframe = document.getElementById('theFrame');
 var message = {
   command: 'render',
   context: {thing: 'world'}
 };
 iframe.contentWindow.postMessage(message, '*');
});
postMessage एपीआई के बारे में सामान्य जानकारी के लिए, एमडीएन पर postMessage का दस्तावेज़ देखें. यह पूरा कॉन्टेंट है और पढ़ने लायक है. खास तौर पर, ध्यान रखें कि डेटा को क्रम से लगाने की सुविधा होने पर ही, उसे आगे-पीछे भेजा जा सकता है. उदाहरण के लिए, फ़ंक्शन नहीं होते हैं.

कुछ खतरनाक करना

sandbox.html के लोड होने पर, यह हैंडलबार लाइब्रेरी को लोड करता है और इनलाइन बनाता है और उसे कंपाइल करता है टेंप्लेट को हैंडलबार के सुझावों के तौर पर देखें:

<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>

ऐसा करने की कोई ज़रूरत नहीं है! भले ही Handlebars.compile, new Function का इस्तेमाल करना बंद कर देता है, लेकिन कुछ न करें जैसा कि उम्मीद है, और आखिर में हमें templates['hello'] में एक कंपाइल किया गया टेंप्लेट मिलता है.

नतीजे को वापस पास करें

हम निर्देशों को स्वीकार करने वाला मैसेज लिसनर सेट अप करके, इस टेंप्लेट को इस्तेमाल के लिए उपलब्ध कराएंगे इवेंट पेज से. हम पास किए गए command का इस्तेमाल करके यह तय करेंगे कि क्या किया जाना चाहिए (आप सिर्फ़ रेंडरिंग से ज़्यादा काम करने के बारे में सोचें; शायद टेंप्लेट बना रहे हैं? शायद उन्हें कुछ जगहों पर मैनेज किया जा रहा है तरीके से मेल खाना चाहिए?) और रेंडरिंग के लिए context को सीधे टेंप्लेट में पास कर दिया जाएगा. रेंडर किया गया एचटीएमएल को इवेंट पेज पर वापस भेज दिया जाएगा, ताकि एक्सटेंशन बाद में इसके साथ कुछ उपयोगी काम कर सके:

<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>

इवेंट पेज पर वापस आने के बाद, हम यह मैसेज भेजेंगे और html के साथ कोई दिलचस्प काम करेंगे वह डेटा है जिसे हमने पास कर दिया है. इस मामले में, हम इसे डेस्कटॉप सूचना के ज़रिए इको करेंगे, लेकिन तो एक्सटेंशन के यूज़र इंटरफ़ेस (यूआई) के हिस्से के रूप में, इस एचटीएमएल का सुरक्षित तरीके से इस्तेमाल किया जा सकता है. इसे से शामिल किया जा रहा है innerHTML से सुरक्षा से जुड़ा कोई ज़्यादा जोखिम नहीं होता, क्योंकि यहां तक कि सैंडबॉक्स वाले सभी गेम को पूरी तरह सुरक्षित किया जा सकता है कुछ चालाक हमलों के ज़रिए कोड में खतरनाक स्क्रिप्ट या प्लगिन को इंजेक्ट नहीं कर पाएगा ज़रूरत के हिसाब से एक्सटेंशन किया जा सकता है.

इस तरीके से टेंप्लेट बनाने का तरीका आसान है. हालांकि, इसमें टेंप्लेट के अलावा और भी चीज़ें शामिल हो सकती हैं. कोई भी ऐसे कोड को सैंडबॉक्स किया जा सकता है जो कॉन्टेंट की सुरक्षा के बारे में सख्त नीति के तहत काम नहीं करता; इंच नहीं, यह आपके एक्सटेंशन के उन कॉम्पोनेंट को सैंडबॉक्स करना अक्सर मददगार होता है जो क्रम से सही तरीके से चलेंगे ताकि आपके प्रोग्राम के हर हिस्से को, उसके लिए ज़रूरी अधिकारों के सबसे छोटे सेट तक सीमित किया जा सके सही तरीके से एक्ज़ीक्यूट होता है. Google का राइटिंग वेब ऐप्लिकेशन और Chrome एक्सटेंशन प्रज़ेंटेशन I/O 2012 में, इन तकनीक के इस्तेमाल के कुछ अच्छे उदाहरण दिए गए हैं और यह आपके लिए समय.