Chrome DevTools में सीएसपी और भरोसेमंद टाइप को डीबग करना लागू करना

Kateryna Prokopenko
Kateryna Prokopenko
Alfonso Castaño
Alfonso Castaño

इस ब्लॉग पोस्ट में, कॉन्टेंट की सुरक्षा के लिए नीति (सीएसपी) से जुड़ी समस्याओं को डीबग करने के लिए, DevTools की सहायता को लागू करने के बारे में बताया गया है. इसके लिए, हाल ही में लॉन्च किए गए समस्याएं टैब की मदद ली गई है.

इसे लागू करने का काम दो इंटर्नशिप के दौरान किया गया: 1. पहले चरण में, हमने सामान्य रिपोर्टिंग फ़्रेमवर्क बनाया और सीएसपी के उल्लंघन से जुड़ी तीन समस्याओं के लिए, समस्या के मैसेज डिज़ाइन किए. 2. दूसरे चरण में, हमने भरोसेमंद टाइप से जुड़ी समस्याओं को जोड़ा. साथ ही, भरोसेमंद टाइप को डीबग करने के लिए, DevTools की कुछ खास सुविधाएं जोड़ीं.

कॉन्टेंट की सुरक्षा के लिए नीति क्या है?

कॉन्टेंट की सुरक्षा के लिए नीति (सीएसपी) की मदद से, वेबसाइट पर कुछ गतिविधियों को सीमित किया जा सकता है, ताकि सुरक्षा को बढ़ाया जा सके. उदाहरण के लिए, सीएसपी का इस्तेमाल करके इनलाइन स्क्रिप्ट या eval को अनुमति देने से रोका जा सकता है. इससे क्रॉस-साइट स्क्रिप्टिंग (XSS) के हमलों का खतरा कम हो जाता है. सीएसपी के बारे में ज़्यादा जानने के लिए, यहां पढ़ें.

सीएसपी का एक नया उदाहरण, ट्रस्टेड टाइप(टीटी) नीति है. यह डाइनैमिक विश्लेषण की सुविधा देती है. इससे वेबसाइटों पर होने वाले कई तरह के इंजेक्शन अटैक को व्यवस्थित तरीके से रोका जा सकता है. इसके लिए, टीटी किसी वेबसाइट के JavaScript कोड की निगरानी करता है. इससे, innerHTML जैसे डीओएम सिंक को सिर्फ़ कुछ खास तरह की चीज़ें असाइन करने की अनुमति मिलती है.

कोई वेबसाइट, किसी खास एचटीटीपी हेडर को शामिल करके, कॉन्टेंट की सुरक्षा के लिए नीति को चालू कर सकती है. उदाहरण के लिए, हेडर content-security-policy: require-trusted-types-for 'script'; trusted-types default किसी पेज के लिए टीटी नीति को चालू करता है.

हर नीति, इनमें से किसी एक मोड में काम कर सकती है:

  • एनफ़ोर्स मोड - इसमें नीति के हर उल्लंघन को गड़बड़ी माना जाता है,
  • सिर्फ़ रिपोर्ट करने वाला मोड - यह गड़बड़ी के मैसेज को चेतावनी के तौर पर रिपोर्ट करता है. हालांकि, इससे वेब पेज पर कोई गड़बड़ी नहीं होती.

समस्याएं टैब में, कॉन्टेंट की सुरक्षा के लिए नीति से जुड़ी समस्याएं लागू करना

इस काम का मकसद, सीएसपी से जुड़ी समस्याओं को डीबग करने के अनुभव को बेहतर बनाना था. नई समस्याओं पर विचार करते समय, DevTools की टीम आम तौर पर इस प्रोसेस को अपनाती है:

  1. उपयोगकर्ता को ध्यान में रखकर प्रॉडक्ट या सेवा की जानकारी देना. DevTools के फ़्रंट-एंड में, उपयोगकर्ता को ध्यान में रखकर प्रॉडक्ट या सेवा की जानकारी देने वाले ऐसे सेट की पहचान करें जिसमें यह बताया गया हो कि वेब डेवलपर को समस्या की जांच कैसे करनी चाहिए.
  2. फ़्रंट-एंड लागू करना. उपयोगकर्ता को ध्यान में रखकर प्रॉडक्ट या सेवा की जानकारी देने के आधार पर, यह पहचान करें कि फ़्रंट-एंड में समस्या की जांच करने के लिए, किस जानकारी की ज़रूरत है. जैसे, कोई मिलती-जुलती रिक्वेस्ट, कुकी का नाम, स्क्रिप्ट या एचटीएमएल फ़ाइल में कोई लाइन वगैरह.
  3. समस्या का पता लगाना. Chrome में उन जगहों की पहचान करें जहां समस्या का पता लगाया जा सकता है. साथ ही, समस्या की शिकायत करने के लिए उस जगह को इंस्ट्रुमेंट करें. इसमें दूसरे चरण की ज़रूरी जानकारी भी शामिल करें.
  4. समस्याओं को सेव करें और दिखाएं. समस्याओं को सही जगह पर सेव करें और DevTools के खुलने पर उन्हें उपलब्ध कराएं
  5. समस्याओं के टेक्स्ट को डिज़ाइन करना. समस्या के बारे में जानकारी देने वाला टेक्स्ट लिखें, ताकि वेब डेवलपर को समस्या समझने में मदद मिले. इससे भी ज़रूरी बात यह है कि वह समस्या को ठीक कर पाए

पहला चरण: सीएसपी से जुड़ी समस्याओं के लिए, उपयोगकर्ता को ध्यान में रखकर प्रॉडक्ट या सेवा की जानकारी देना

लागू करने से पहले, हमने उपयोगकर्ता को ध्यान में रखकर प्रॉडक्ट या सेवा की जानकारी देने वाला डिज़ाइन दस्तावेज़ बनाया, ताकि हम बेहतर तरीके से समझ सकें कि हमें क्या करना है. उदाहरण के लिए, हमने उपयोगकर्ता को ध्यान में रखकर प्रॉडक्ट या सेवा की जानकारी देने वाला यह दस्तावेज़ लिखा:


एक डेवलपर के तौर पर, मुझे अभी पता चला है कि मेरी वेबसाइट के कुछ हिस्से ब्लॉक कर दिए गए हैं. मुझे:- - ...यह पता लगाना है कि क्या सीएसपी की वजह से, मेरी वेबसाइट पर iframe / इमेज ब्लॉक की गई हैं - ...यह जानना है कि किस सीएसपी डायरेक्टिव की वजह से, किसी संसाधन को ब्लॉक किया गया है - ...यह जानना है कि मेरी वेबसाइट के सीएसपी में कैसे बदलाव किया जाए, ताकि फ़िलहाल ब्लॉक किए गए संसाधनों को दिखाया जा सके / फ़िलहाल ब्लॉक की गई js को लागू किया जा सके.


उपयोगकर्ता को ध्यान में रखकर प्रॉडक्ट या सेवा की जानकारी देने के लिए, हमने कुछ आसान उदाहरण वाले वेब पेज बनाए. इनमें सीएसपी के उन उल्लंघनों को दिखाया गया जिनमें हमारी दिलचस्पी थी. साथ ही, हमने उदाहरण वाले पेजों को एक्सप्लोर किया, ताकि हम खुद इस प्रोसेस को समझ सकें. यहां कुछ वेब पेजों के उदाहरण दिए गए हैं. समस्याएं टैब खोलकर डेमो देखें:

इस प्रोसेस का इस्तेमाल करके, हमें पता चला कि सीएसपी से जुड़ी समस्याओं को डीबग करने के लिए, सोर्स की जगह की जानकारी सबसे अहम होती है. हमें यह भी पता चला कि अगर कोई संसाधन ब्लॉक किया गया है, तो उससे जुड़े iframe और अनुरोध को तुरंत ढूंढना मददगार होता है. साथ ही, DevTools के एलिमेंट पैनल में एचटीएमएल एलिमेंट का डायरेक्ट लिंक भी मददगार हो सकता है.

दूसरा चरण: फ़्रंट-एंड लागू करना

हमने इस अहम जानकारी को उस जानकारी के पहले ड्राफ़्ट में बदल दिया जिसे हम Chrome DevTools प्रोटोकॉल (सीडीपी) के ज़रिए DevTools को उपलब्ध कराना चाहते थे:

third_party/blink/public/devtools_protocol/browser_protocol.pdl का अंश नीचे दिया गया है

 type ContentSecurityPolicyIssueDetails extends object
   properties
     # The url not included in allowed sources.
     optional string blockedURL
     # Specific directive that is violated, causing the CSP issue.
     string violatedDirective
     boolean isReportOnly
     ContentSecurityPolicyViolationType contentSecurityPolicyViolationType
     optional AffectedFrame frameAncestor
     optional SourceCodeLocation sourceCodeLocation
     optional DOM.BackendNodeId violatingNodeId

ऊपर दी गई परिभाषा, JSON डेटा-स्ट्रक्चर को एन्कोड करती है. इसे पीडीएल (प्रोटोकॉल डेटा लैंग्वेज) नाम की आसान भाषा में लिखा जाता है. पीडीएल का इस्तेमाल दो कामों के लिए किया जाता है. सबसे पहले, हम पीडीएल का इस्तेमाल करके TypeScript डेफ़िनिशन जनरेट करते हैं. DevTools का फ़्रंट-एंड इन डेफ़िनिशन पर निर्भर करता है. उदाहरण के लिए, ऊपर दी गई पीडीएल डेफ़िनिशन, यह TypeScript इंटरफ़ेस जनरेट करती है:

export interface ContentSecurityPolicyIssueDetails {
  /**
  * The url not included in allowed sources.
  */
  blockedURL?: string;
  /**
  * Specific directive that is violated, causing the CSP issue.
  */
  violatedDirective: string;
  isReportOnly: boolean;
  contentSecurityPolicyViolationType: ContentSecurityPolicyViolationType;
  frameAncestor?: AffectedFrame;
  sourceCodeLocation?: SourceCodeLocation;
  violatingNodeId?: DOM.BackendNodeId;
}

दूसरा और शायद ज़्यादा अहम यह है कि हम डेफ़िनिशन से एक C++ लाइब्रेरी जनरेट करते हैं. यह लाइब्रेरी, C++ Chromium बैक-एंड से DevTools फ़्रंट-एंड तक इन डेटा स्ट्रक्चर को जनरेट करने और भेजने का काम करती है. उस लाइब्रेरी का इस्तेमाल करके, C++ कोड के इस हिस्से का इस्तेमाल करके ContentSecurityPolicyIssueDetails ऑब्जेक्ट बनाया जा सकता है:

protocol::Audits::ContentSecurityPolicyIssueDetails::create()
  .setViolatedDirective(d->violated_directive)
  .setIsReportOnly(d->is_report_only)
  .setContentSecurityPolicyViolationType(BuildViolationType(
      d->content_security_policy_violation_type)))
  .build();

यह तय करने के बाद कि हमें कौनसी जानकारी उपलब्ध करानी है, हमें यह देखना था कि Chromium से यह जानकारी कहां से मिलेगी.

तीसरा चरण: समस्या का पता लगाना

पिछले सेक्शन में बताए गए फ़ॉर्मैट में, Chrome DevTools Protocol (सीडीपी) को जानकारी उपलब्ध कराने के लिए, हमें वह जगह ढूंढनी पड़ी जहां बैक-एंड में जानकारी असल में उपलब्ध थी. अच्छी बात यह है कि सीएसपी कोड में पहले से ही सिर्फ़ रिपोर्ट मोड के लिए एक बॉटल-नेक था, जहां हम हुक कर सकते थे: ContentSecurityPolicy::ReportViolation, समस्याओं की शिकायत (ज़रूरी नहीं) रिपोर्टिंग एंड-पॉइंट पर करता है. इसे सीएसपी एचटीटीपी हेडर में कॉन्फ़िगर किया जा सकता है. हमें जो जानकारी रिपोर्ट करनी थी उसमें से ज़्यादातर जानकारी पहले से ही उपलब्ध थी. इसलिए, हमारे इंस्ट्रुमेंटेशन को काम करने के लिए, बैक-एंड में कोई बड़ा बदलाव करने की ज़रूरत नहीं थी.

चौथा चरण: समस्याओं को सेव करना और दिखाना

एक छोटी सी समस्या यह है कि हम DevTools को खोलने से पहले हुई समस्याओं की भी रिपोर्ट करना चाहते थे. ठीक उसी तरह जैसे कंसोल मैसेज को मैनेज किया जाता है. इसका मतलब है कि हम समस्याओं की जानकारी सीधे फ़्रंट-एंड को नहीं देते. इसके बजाय, हम एक ऐसे स्टोरेज का इस्तेमाल करते हैं जिसमें समस्याएं अपने-आप भर जाती हैं. भले ही, DevTools खुला हो या नहीं. DevTools खोलने या किसी अन्य सीडीपी क्लाइंट को अटैच करने के बाद, पहले से रिकॉर्ड की गई सभी समस्याओं को स्टोरेज से फिर से चलाया जा सकता है.

इससे बैक-एंड का काम पूरा हो गया. अब हमें इस बात पर ध्यान देना था कि फ़्रंट-एंड में समस्या को कैसे दिखाया जाए.

पांचवां चरण: समस्याओं के टेक्स्ट को डिज़ाइन करना

समस्याओं के बारे में बताने वाला टेक्स्ट तैयार करने की प्रोसेस में, हमारी टीम के अलावा कई अन्य टीमें भी शामिल होती हैं. उदाहरण के लिए, हम अक्सर उस टीम से मिली अहम जानकारी पर भरोसा करते हैं जो किसी सुविधा को लागू करती है. इस मामले में, यह सीएसपी टीम होगी. इसके अलावा, डेवलपर रिलेशन टीम भी इसमें शामिल होती है. यह टीम यह तय करती है कि वेब डेवलपर को किसी खास तरह की समस्या से कैसे निपटना चाहिए. समस्या के टेक्स्ट को आम तौर पर तब तक बेहतर बनाया जाता है, जब तक वह पूरी तरह से तैयार नहीं हो जाता.

आम तौर पर, DevTools की टीम अपनी कल्पना के आधार पर एक रफ़ ड्राफ़्ट से शुरुआत करती है:


## Header
Content Security Policy: include all sources of your resources in content security policy header to improve the functioning of your site

## General information
Even though some sources are included in the content security policy header, some resources accessed by your site like images, stylesheets or scripts originate from sources not included in content security policy directives.

Usage of content from not included sources is restricted to strengthen the security of your entire site.

## Specific information

### VIOLATED DIRECTIVES
`img-src 'self'`

### BLOCKED URLs
https://imgur.com/JuXCo1p.jpg

## Specific information
https://web.dev/strict-csp/

कई बार दोहराने के बाद, हम इस नतीजे पर पहुंचे:

ALT_TEXT_HERE

जैसा कि आपने देखा, सुविधा बनाने वाली टीम और DevRel को शामिल करने से, जानकारी ज़्यादा साफ़ और सटीक हो जाती है!

आपके पेज पर मौजूद सीएसपी से जुड़ी समस्याओं का पता, सीएसपी के उल्लंघनों के लिए खास तौर पर बनाए गए टैब में भी लगाया जा सकता है.

ट्रस्टेड टाइप से जुड़ी समस्याओं को डीबग करना

सही डेवलपर टूल के बिना, बड़े पैमाने पर टीटी के साथ काम करना मुश्किल हो सकता है.

कंसोल प्रिंटिंग की सुविधा को बेहतर बनाया गया

भरोसेमंद ऑब्जेक्ट के साथ काम करते समय, हम कम से कम उतनी जानकारी दिखाना चाहते हैं जितनी गैर-भरोसेमंद ऑब्जेक्ट के लिए दिखाई जाती है. फ़िलहाल, किसी भरोसेमंद ऑब्जेक्ट को दिखाते समय, रैप किए गए ऑब्जेक्ट के बारे में कोई जानकारी नहीं दिखाई जाती.

ऐसा इसलिए होता है, क्योंकि कंसोल में दिखने वाली वैल्यू, डिफ़ॉल्ट रूप से ऑब्जेक्ट पर .valueOf() को कॉल करने से ली जाती है. हालांकि, ट्रस्टेड टाइप के मामले में, रिटर्न की गई वैल्यू ज़्यादा काम की नहीं होती. इसके बजाय, हम चाहते हैं कि आपको .toString() पर कॉल करने पर मिलने वाली सुविधा जैसा कुछ मिले. इसके लिए, हमें V8 और Blink में बदलाव करना होगा, ताकि भरोसेमंद टाइप ऑब्जेक्ट को खास तरीके से मैनेज किया जा सके.

हालांकि, ऐतिहासिक वजहों से यह कस्टम हैंडलिंग V8 में की गई थी, लेकिन इस तरीके के कई अहम नुकसान हैं. ऐसे कई ऑब्जेक्ट होते हैं जिन्हें पसंद के मुताबिक दिखाने की ज़रूरत होती है. हालांकि, JS लेवल पर उनका टाइप एक ही होता है. V8 पूरी तरह से JS है. इसलिए, यह वेब एपीआई से जुड़े कॉन्सेप्ट में अंतर नहीं कर सकता. जैसे, भरोसेमंद टाइप. इस वजह से, V8 को अपने एंबेडर (Blink) से मदद लेनी पड़ती है, ताकि वह दोनों के बीच अंतर कर सके.

इसलिए, कोड के उस हिस्से को Blink या किसी एंबेडर पर ले जाना एक सही विकल्प लगता है. इस समस्या को हल करने के अलावा, इसके और भी कई फ़ायदे हैं:

  • हर एंबेडर के पास ब्यौरा जनरेट करने की अपनी सुविधा हो सकती है
  • Blink API की मदद से, ब्यौरा जनरेट करना काफ़ी आसान है
  • Blink के पास ऑब्जेक्ट की ओरिजनल डेफ़िनिशन का ऐक्सेस होता है. इसलिए, अगर हम ब्यौरा जनरेट करने के लिए .toString() का इस्तेमाल करते हैं, तो इस बात का कोई खतरा नहीं है कि .toString() को फिर से तय किया जा सकता है.

Break-on-violation (सिर्फ़ रिपोर्ट करने वाले मोड में)

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

DevTools में पहले से ही कई तरह के ब्रेकपॉइंट काम करते हैं. इसलिए, आर्किटेक्चर को आसानी से बढ़ाया जा सकता है. ब्रेकपॉइंट का नया टाइप जोड़ने के लिए, बैकएंड (Blink), सीडीपी, और फ़्रंटएंड में बदलाव करने होंगे. हमें एक नया सीडीपी कमांड बनाना चाहिए. चलिए, इसे setBreakOnTTViolation नाम देते हैं. इस निर्देश का इस्तेमाल फ़्रंटएंड, बैकएंड को यह बताने के लिए करेगा कि उसे किस तरह के टीटी उल्लंघन पर रुकना चाहिए. बैकएंड, खास तौर पर InspectorDOMDebuggerAgent, एक "प्रोब" onTTViolation() उपलब्ध कराएगा. इसे हर बार टीटी के उल्लंघन के समय कॉल किया जाएगा. इसके बाद, InspectorDOMDebuggerAgent यह जांच करेगा कि क्या उस उल्लंघन से ब्रेकपॉइंट ट्रिगर होना चाहिए. अगर ऐसा है, तो वह एक्ज़ीक्यूशन को रोकने के लिए फ़्रंटएंड को एक मैसेज भेजेगा.

अब तक क्या किया गया है और आगे क्या करना है?

यहां बताई गई समस्याओं के बाद, समस्याएं टैब में काफ़ी बदलाव किए गए हैं:

आने वाले समय में, हम समस्याएं टैब का इस्तेमाल करके ज़्यादा समस्याएं दिखाएंगे. इससे, लंबे समय में गड़बड़ी के मैसेज के ऐसे फ़्लो को कंसोल से हटाया जा सकेगा जिसे पढ़ा नहीं जा सकता.

झलक दिखाने वाले चैनल डाउनलोड करना

Chrome Canary, Dev या Beta को अपने डिफ़ॉल्ट डेवलपमेंट ब्राउज़र के तौर पर इस्तेमाल करें. इन झलक वाले चैनलों से, आपको DevTools की नई सुविधाओं का ऐक्सेस मिलता है. साथ ही, आपको वेब प्लैटफ़ॉर्म के नए एपीआई को टेस्ट करने की सुविधा मिलती है. इसके अलावा, आपको अपनी साइट पर मौजूद समस्याओं का पता लगाने में मदद मिलती है. इससे आपको उपयोगकर्ताओं से पहले ही समस्याओं का पता चल जाता है!

Chrome DevTools की टीम से संपर्क करें

DevTools से जुड़ी नई सुविधाओं, अपडेट या किसी अन्य विषय पर चर्चा करने के लिए, इन विकल्पों का इस्तेमाल करें.