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

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

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

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

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

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

من بين ميزات 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 في لوحة العناصر في "أدوات المطوّر" قد يكون مفيدًا أيضًا.

الخطوة 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 خالص، لا يمكنه التمييز بين المفاهيم التي تتوافق مع Web API، مثل النوع الموثوق. لهذا السبب، على V8 طلب المساعدة من أداة التضمين (Blink) للتمييز بينهما.

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

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

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

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

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

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

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

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

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

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

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

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