تنفيذ تصحيح أخطاء سياسة أمان المحتوى (CSP) والأنواع الموثوق بها في "أدوات مطوري البرامج في Chrome"

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

تتناول هذه المقالة على المدوّنة تنفيذ ميزة تتيح استخدام أدوات مطوّري البرامج لتصحيح أخطاء سياسة أمان المحتوى (CSP) باستخدام علامة التبويب المشاكل التي تمّ طرحها مؤخرًا.

وتم الانتهاء من التنفيذ خلال دورتين تدريبيتين: 1. خلال المرحلة الأولى، أنشأنا إطار عمل إعداد التقارير العام وصمّمنا رسائل المشاكل المتعلّقة بثلاثة انتهاكات لسياسة "شركاء المحتوى في خرائط Google". 2. خلال الإصدار الثاني، أضفنا مشاكل "الأنواع الموثوق بها" إلى جانب بعض ميزات DevTools المتخصصة لتصحيح أخطاء "الأنواع الموثوق بها".

ما هي "سياسة أمان المحتوى"؟

تسمح سياسة أمان المحتوى (CSP) بحظر سلوكيات معيّنة في موقع إلكتروني لزيادة مستوى الأمان. على سبيل المثال، يمكن استخدام سياسة CSP لحظر النصوص البرمجية المضمّنة أو لحظر eval، وكلاهما يقلل من مساحة الهجوم في هجمات النصوص البرمجية على المواقع الإلكترونية (XSS). للاطّلاع على مقدمة مفصّلة عن سياسة CSP، يُرجى قراءة المعلومات هنا.

إنّ سياسة CSP الجديدة بشكل خاص هي سياسة الأنواع الموثوق بها(TT) التي تتيح تحليلاً ديناميكيًا يمكنه أن يمنع بشكل منهجي فئة كبيرة من هجمات الحقن على المواقع الإلكترونية. ولتحقيق ذلك، يساعد TT الموقع الإلكتروني في التحكّم في رمز JavaScript الخاص به للسماح فقط بتخصيص أنواع معيّنة من العناصر لمصارف DOM، مثل innerHTML.

يمكن لموقع إلكتروني تفعيل سياسة أمان المحتوى من خلال تضمين عنوان HTTP معيّن. على سبيل المثال، يؤدي العنوان content-security-policy: require-trusted-types-for 'script'; trusted-types default إلى تفعيل سياسة TT لصفحة معيّنة.

يمكن أن تعمل كل سياسة في أحد الوضعَين التاليَين:

  • الوضع المفروض: حيث يكون كل انتهاك للسياسة خطأ،
  • وضع إعداد التقارير فقط: الذي يُبلغ عن رسالة الخطأ باعتبارها تحذيرًا، ولكنّه لا يؤدي إلى حدوث خطأ في صفحة الويب.

تنفيذ "مشاكل أمان المحتوى" في علامة التبويب المشاكل

كان الهدف من هذا العمل هو تحسين تجربة تصحيح أخطاء مشاكل "سياسة الخدمات في المواقع". عند النظر في المشاكل الجديدة، يتّبع فريق أدوات المطوّرين هذه العملية تقريبًا:

  1. تحديد قصص المستخدمين حدِّد مجموعة من قصص المستخدمين في الواجهة الأمامية لـ "أدوات مطوري البرامج" والتي تتناول كيف سيحتاج مطوِّر الويب إلى التحقيق في المشكلة.
  2. تنفيذ الواجهة الأمامية: استنادًا إلى قصص المستخدمين، حدِّد المعلومات المطلوبة للتحقيق في المشكلة في الواجهة الأمامية (مثل طلب ذي صلة أو اسم ملف تعريف ارتباط أو سطر في نص برمجي أو ملف html، وما إلى ذلك).
  3. اكتشاف المشاكل: حدِّد الأماكن في المتصفّح التي يمكن رصد المشكلة فيها في Chrome، وفعِّل المكان للإبلاغ عن مشكلة مع تضمين المعلومات ذات الصلة من الخطوة (2).
  4. حفظ المشاكل وعرضها: تخزين المشاكل في مكان مناسب وإتاحتها على "أدوات مطوري البرامج" بعد فتحها
  5. تصميم نص المشاكل: أنشئ نصًا توضيحيًا يساعد مطوّر الويب في فهم المشكلة وحلّها، والأهم من ذلك

الخطوة 1: تحديد قصص المستخدمين لمشاكل خدمة إدارة المحتوى (CSP)

قبل بدء عمل التنفيذ، أنشأنا مستند تصميم يتضمّن قصص مستخدمين لفهم ما علينا فعله بشكل أفضل. على سبيل المثال، سجّلنا قصة المستخدم التالية:


بصفتي مطوّرًا، اكتشفت للتو أنّ بعض أجزاء موقعي الإلكتروني محظورة، وأريد:- - ...معرفة ما إذا كان تنسيق CSP هو سبب حظر إطارات iframe أو الصور على موقعي الإلكتروني - ...معرفة توجيه CSP الذي يتسبب في حظر مورد معيّن - ...معرفة كيفية تغيير تنسيق CSP لموقعي الإلكتروني للسماح بعرض الموارد المحظورة حاليًا أو تنفيذ JavaScript المحظور حاليًا.


لاستكشاف قصة المستخدم هذه، أنشأنا بعض الأمثلة البسيطة لصفحات الويب التي تعرضت لانتهاكات بروتوكول CSP التي تهمّنا، واستكشَفنا أمثلة الصفحات للتعرّف على العملية بأنفسنا. في ما يلي بعض أمثلة صفحات الويب (افتح العرض الترويجي مع فتح علامة التبويب المشاكل):

باستخدام هذه العملية، تبيّن لنا أنّ الموقع الجغرافي للمصدر هو أهم المعلومات لتصحيح أخطاء CSP. تبيّن لنا أيضًا أنّه من المفيد العثور بسرعة على إطار iframe والطلب المرتبط به في حال حظر أحد الموارد، وأنّ الرابط المباشر إلى عنصر HTML في لوحة العناصر في DevTools قد يكون مفيدًا أيضًا.

الخطوة 2: تنفيذ الواجهة الأمامية

لقد حوّلنا هذه الإحصاءات إلى المسودة الأولى للمعلومات التي أردنا إتاحتها في "أدوات مطوّري البرامج" من خلال بروتوكول أدوات مطوّري البرامج في Chrome (CDP):

في ما يلي مقتطف من 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. فهي مكتوبة بلغة بسيطة تسمى PDL (لغة بيانات البروتوكول). يتم استخدام ملف PDL لغرضَين. أولاً، نستخدم PDL لإنشاء تعريفات TypeScript التي تعتمد عليها الواجهة الأمامية لواجهة المطوّرين. على سبيل المثال، ينشئ تعريف PDL أعلاه واجهة 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. باستخدام هذه المكتبة، يمكن إنشاء عنصر ContentSecurityPolicyIssueDetails باستخدام القطعة التالية من رمز C++:

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

بعد أن حدّدنا المعلومات التي نريد إتاحتها، كان علينا استكشاف مكان الحصول على هذه المعلومات من Chromium.

الخطوة 3: رصد المشكلة

لتوفير المعلومات لبروتوكول Chrome DevTools (CDP) بالتنسيق الموضّح في القسم الأخير، كان علينا العثور على المكان الذي تتوفّر فيه المعلومات فعليًا في الخلفية. لحسن الحظ، كان رمز CSP يتضمّن بالفعل مشكلة في وضع "إعداد التقارير فقط"، حيث يمكننا الربط بما يلي: ContentSecurityPolicy::ReportViolation للإبلاغ عن المشاكل إلى نقطة نهاية (اختيارية) لإعداد التقارير يمكن ضبطها في عنوان HTTP الخاص بـ CSP. كانت معظم المعلومات التي أردنا الإبلاغ عنها متاحة، لذا لم تكن هناك حاجة إلى إجراء تغييرات كبيرة في الخلفية لكي تعمل أدواتنا.

الخطوة 4: حفظ المشاكل وعرضها

هناك تعقيد بسيط وهو أنّنا أردنا أيضًا الإبلاغ عن المشاكل التي حدثت قبل فتح DevTools، تمامًا مثل طريقة معالجة رسائل وحدة التحكّم. وهذا يعني أنّنا لا نبلِغ عن المشاكل مباشرةً إلى الواجهة الأمامية، ولكنّنا نستخدم مساحة تخزين يتمّ تعبئتها بالمشاكل بغض النظر عمّا إذا كانت "أدوات مطوّري البرامج" مفتوحة أم لا. بعد فتح أدوات مطوّري البرامج (أو إرفاق أيّ عميل آخر لخدمة "إدارة بيانات العملاء")، يمكن إعادة تشغيل جميع المشاكل المسجّلة سابقًا من مساحة التخزين.

وقد انتهى ذلك من عمل الواجهة الخلفية، ونحتاج الآن إلى التركيز على كيفية إظهار المشكلة في الواجهة الأمامية.

الخطوة 5: تصميم نص المشكلات

إنّ تصميم نص المشاكل هو عملية تتطلّب مشاركة عدة فِرق بالإضافة إلى فريقنا. على سبيل المثال، غالبًا ما نعتمد على إحصاءات من الفريق الذي ينفّذ إحدى الميزات (في هذه الحالة، سيكون فريق CSP) وبالطبع فريق DevRel الذي يصمّم كيفية تعامل مطوّري الويب مع نوع معيّن من المشاكل. يخضع نص المشكلة عادةً لبعض التحسينات إلى أن يكتمل.

عادةً ما يبدأ فريق 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

كما ترى، يؤدي إشراك فريق الميزات وفريق العلاقات المطوّرين إلى جعل الوصف أكثر وضوحًا ودقة.

يمكن أيضًا اكتشاف مشاكل سياسة أمان المحتوى (CSP) على صفحتك في علامة التبويب المخصّصة تحديدًا لسياسة CSP.

تصحيح أخطاء Trusted Types

قد يكون من الصعب استخدام TT على نطاق واسع بدون أدوات المطوّرين المناسبة.

تحسين الطباعة في وحدة التحكّم

عند العمل مع "العناصر الموثوق بها"، نريد عرض القدر نفسه من المعلومات على الأقلّ مثل العنصر غير الموثوق به. للأسف، عند عرض كائن موثوق به، لا يتم حاليًا عرض أي معلومات عن الكائن الملفوف.

ويعود السبب في ذلك إلى أنّ القيمة المعروضة في وحدة التحكّم مأخوذة من استدعاء .valueOf() على العنصر تلقائيًا. ومع ذلك، في حال النوع الموثوق به، لا تكون القيمة المعروضة مفيدة جدًا. بدلاً من ذلك، نريد أن نقدّم لك تجربة مشابهة لما تحصل عليه عند الاتصال برقم .toString(). لتحقيق ذلك، علينا تعديل V8 وBlink لتوفير معالجة خاصة للكائنات من النوع الموثوق.

على الرغم من أنّه تم إجراء هذا المعالجة المخصّصة في الإصدار 8 لأسباب تاريخية، إلا أنّ هذا النهج له عيوب مهمة. هناك العديد من العناصر التي تتطلب عرضًا مخصّصًا ولكن نوعها هو نفسه على مستوى JavaScript. نظرًا لأن V8 هو مجرد JavaScript، لا يمكنه التمييز بين المفاهيم التي تتوافق مع واجهة برمجة تطبيقات الويب مثل النوع الموثوق به. لهذا السبب، على V8 طلب المساعدة من أداة التضمين (Blink) للتمييز بينهما.

وبالتالي، فإن نقل هذا الجزء من الرمز إلى Blink أو أي برنامج تضمين يبدو اختيارًا منطقيًا. بالإضافة إلى المشكلة التي تم رصدها، هناك العديد من المزايا الأخرى:

  • يمكن أن تنشئ كل أداة تضمين وصفها الخاص
  • من الأسهل إنشاء الوصف من خلال Blink API.
  • يمكن لتطبيق Blink الوصول إلى التعريف الأصلي للعنصر. وبالتالي، إذا استخدمنا .toString() لإنشاء الوصف، ليس هناك خطر في أن يتم إعادة تعريف السمة .toString().

إيقاف الفحص عند حدوث انتهاك (في وضع إعداد التقارير فقط)

في الوقت الحالي، الطريقة الوحيدة لتصحيح أخطاء أخطاء TT هي تحديد نقاط توقف على استثناءات JavaScript. وبما أنّ انتهاكات TT المفروضة ستؤدي إلى ظهور استثناء، يمكن أن تكون هذه الميزة مفيدة إلى حدّ ما. ومع ذلك، في السيناريوهات الواقعية، تحتاج إلى التحكّم بشكل أدق في انتهاكات TT. وعلى وجه الخصوص، نرغب في التقسيم فقط على انتهاكات TT (وليس استثناءات أخرى)، كما نرغب في الفصل أيضًا في وضع إعداد التقارير فقط والتمييز بين الأنواع المختلفة من انتهاكات TT.

تتيح "أدوات المطوّر" حاليًا مجموعة كبيرة من نقاط التوقف، لذا فإنّ البنية قابلة للتوسيع إلى حدٍ كبير. تتطلّب إضافة نوع نقطة توقّف جديد تغييرات في الخلفية (Blink) وCDP والواجهة الأمامية. يجب أن نقدم أمر CDP جديدًا، اسمه setBreakOnTTViolation. ستستخدم الواجهة الأمامية هذا الأمر لإعلام الواجهة الخلفية بنوع انتهاكات TT التي يجب معالجتها. ستقدم الخلفية، لا سيما InspectorDOMDebuggerAgent، "تحقيقًا"، onTTViolation() سيتم استدعاؤه في كل مرة يحدث فيها انتهاك لـ TT. بعد ذلك، سيتحقّق InspectorDOMDebuggerAgent ممّا إذا كان يجب أن يؤدي هذا الانتهاك إلى تنشيط نقطة توقف، وإذا كان الأمر كذلك، سيرسل رسالة إلى الواجهة الأمامية لإيقاف التنفيذ مؤقتًا.

ما الذي تم إنجازه وما هي الخطوة التالية؟

منذ ظهور المشاكل الموضّحة هنا، شهدت علامة التبويب المشاكل بعض التغييرات:

من الآن فصاعدًا، نخطّط لاستخدام علامة التبويب المشاكل لعرض المزيد من المشاكل، ما سيتيح إلغاء تحميل وحدة التحكّم الخاصة بمسار رسائل الخطأ غير القابلة للقراءة على المدى الطويل.

تنزيل قنوات المعاينة

ننصحك باستخدام إصدار Canary أو Dev أو الإصدار التجريبي من Chrome كمتصفّح التطوير التلقائي. تتيح لك قنوات المعاينة هذه الوصول إلى أحدث ميزات "أدوات مطوري البرامج"، واختبار واجهات برمجة التطبيقات الأكثر تطوّرًا للأنظمة الأساسية للويب، كما تساعدك في العثور على المشاكل على موقعك الإلكتروني قبل أن يكتشفها المستخدمون.

التواصل مع فريق "أدوات مطوّري البرامج في Chrome"

استخدِم الخيارات التالية لمناقشة الميزات الجديدة أو التحديثات أو أي شيء آخر مرتبط بـ "أدوات مطوّري البرامج".