سياسة أمان المحتوى وCMP: كيف تعمل CSP والموافقة معًا
طبقتا أمان يجب أن تتفقا
تخبر سياسة أمان المحتوى (CSP) المتصفح بالمصادر التي يجوز للصفحة تحميل السكربتات والأنماط والصور والإطارات وطلبات الشبكة منها. أما منصة إدارة الموافقة فتؤدي المهمة المعاكسة: تقرر أي هذه السكربتات يُسمح له بالعمل بناءً على اختيار المستخدم. وحين يُضبط الاثنان بمعزل عن بعضهما يتصادمان. إما يفشل CMP في التحميل لأن CSP تحجبه، وإما تُخفَّف CSP كثيرًا لاستيعاب CMP ووسوم الإعلانات حتى لا تعود تحمي شيئًا.
يشرح هذا الدليل التوجيهات التي يحتاجها CMP عادةً من CSP، وكيف تتفاعل قيم nonce مع حقن السكربتات، وكيف تطبّق التغييرات دون كسر البانر.
ما يحتاجه CMP عادةً من CSP
تعتمد المتطلبات الدقيقة على المزوّد، لذا ابدأ دائمًا من وثائق CMP الخاصة بك. وبصورة عامة، افحص هذه التوجيهات:
script-src— النطاق الذي يُحمَّل منه سكربت CMP، إضافةً إلى أي ملفات سكربت إضافية يحمّلها.connect-src— نقاط النهاية التي يستدعيها CMP عبرfetchأو XHR، مثل الإعدادات وقائمة المزوّدين والموقع الجغرافي وتسجيل الموافقة.style-src— نطاق ورقة الأنماط، وربما الأنماط المضمّنة إذا كان CMP يحقن عنصر<style>أو يضبط سمات style.img-src— الشعارات والأيقونات وأي بكسلات خالية من التتبع يستخدمها CMP.font-src— إذا كان البانر يحمّل خطوطه الخاصة.frame-src— إذا كان CMP يستخدم iframes، مثلًا لمشاركة الموافقة عبر النطاقات.
في مواقع TCF، تذكّر أن CMP ينشئ أيضًا إطارًا محدِّدًا باسم __tcfapiLocator في الصفحة. يُنشأ هذا الإطار دون مصدر بعيد، فلا يحتاج عادةً إلى إدخال في frame-src، لكن من المفيد التأكد من ذلك أثناء الاختبار.
مشكلة الـ Stub المضمّن
تطلب منك معظم أنظمة CMP وضع سكربت صغير مضمّن — الـ stub — في رأس الصفحة، حتى تتمكن السكربتات الأخرى من وضع استدعاءاتها في الطابور قبل تحميل CMP الرئيسي. تحجب CSP الصارمة السكربتات المضمّنة ما لم تسمح بها صراحةً. أمامك ثلاثة خيارات:
- قيمة nonce. أنشئ قيمة عشوائية لكل استجابة، وأضفها إلى ترويسة CSP على هيئة
'nonce-...'وإلى وسم<script>الخاص بالـ stub. هذا هو الخيار الأكثر مرونة للصفحات الديناميكية. - تجزئة (hash). أضف تجزئة SHA-256 لمحتوى الـ stub بالضبط إلى
script-src. يناسب هذا المواقع الثابتة، لكن أي تغيير في الـ stub، حتى مسافة بيضاء، يكسره. - استضافة الـ stub ذاتيًا كملف خارجي على نطاقك، تغطيه
'self'. يتطلب هذا عناية لضمان تحميله مبكرًا بما يكفي.
تجنّب 'unsafe-inline' كاختصار. فهو يسمح بكل سكربت مضمّن، مما يزيل الكثير من الحماية التي توفرها CSP.
قيم nonce والسكربتات التي يحقنها CMP
غالبًا ما يعمل CMP الذي يحجب السكربتات إلى حين الموافقة بحجزها ثم حقنها لاحقًا. وفي ظل CSP قائمة على nonce يجب السماح بتلك السكربتات المحقونة أيضًا. هناك نهجان شائعان:
- تمرير nonce. يقرأ CMP قيمة nonce من وسم السكربت الخاص به ويضيفها إلى كل سكربت يحقنه. تحقق مما إذا كان CMP لديك يدعم ذلك.
'strict-dynamic'. تخبر هذه الكلمة المفتاحية المتصفحات الداعمة بأن تثق بالسكربتات التي يحمّلها سكربت موثوق أصلًا. تسهّل الحياة مع مديري الوسوم وأنظمة CMP التي تحقن السكربتات، لكنها تعني أيضًا أن أي سكربت تثق به يمكنه تحميل غيره، فثق بحذر.
يثير مديرو الوسوم السؤال نفسه. إذا كنت تحمّل وسوم الإعلانات والتحليلات عبر مدير وسوم، فاتبع وثائقه بشأن قيم nonce وتأكد من أن CMP ومدير الوسوم يستخدمان نهجًا متسقًا.
وسوم الإعلانات تجعل CSP أصعب
يحمّل الإعلان البرمجي سكربتات وإطارات من نطاقات عديدة، وتتغير القائمة بتغير شركاء الطلب. يتخذ الناشرون عادةً أحد خيارين:
- CSP صارمة في الصفحات التي لا تحتوي على إعلانات برمجية، وسياسة أوسع حيث تعمل الإعلانات.
- سياسة تركز على التوجيهات التي يمكن إدارتها، مثل
frame-ancestorsوobject-src 'none'وbase-uri، بينما تبقى مصادر السكربتات أوسع.
وفي الحالتين ينبغي أن يكون CMP في قائمة السماح الصريحة، لا مشمولًا بحرف بدل فقط، حتى لا يعطّل أي تغيير في CSP البانر بصمت.
اطرح التغيير بوضع Report-Only
استخدم ترويسة Content-Security-Policy-Report-Only أولًا. يبلغ المتصفح عن الانتهاكات دون حجب أي شيء، فترى ما الذي ستكسره السياسة الجديدة.
- انشر السياسة في وضع report-only مع نقطة نهاية للتقارير.
- حمّل الصفحات في ملفات تعريف متصفح نظيفة وأكمل مسار الموافقة بالكامل: الزيارة الأولى، قبول الكل، رفض الكل، اختيار مخصص، سحب الموافقة.
- راجع تقارير الانتهاكات ووحدة تحكم المتصفح بحثًا عن موارد CMP المحجوبة.
- عدّل السياسة ثم انتقل إلى الإنفاذ.
- أبقِ الإبلاغ مفعّلًا بعد الإنفاذ لاكتشاف حالات التراجع.
أعراض تعارض CSP
- لا يظهر البانر أبدًا، وتعرض وحدة التحكم انتهاك CSP لسكربت CMP.
- يظهر البانر لكن بلا تنسيق، لأن
style-srcيحجب CSS الخاص به. - لا تُحفظ الاختيارات، لأن
connect-srcيحجب استدعاء تسجيل الموافقة. - لا تُحمَّل الإعلانات أو التحليلات أبدًا بعد الموافقة، لأن السكربتات المحقونة تفتقر إلى nonce.
- الدالة
__tcfapiغير معرّفة، لأن الـ stub المضمّن حُجب.
أهم النقاط
- افحص
script-srcوconnect-srcوstyle-srcوimg-srcوframe-srcلـ CMP الخاص بك. - اسمح بالـ stub المضمّن عبر nonce أو hash، لا عبر
'unsafe-inline'. - تأكد من أن السكربتات المحقونة بعد الموافقة تتلقى nonce أو تشملها
'strict-dynamic'. - اختبر كل مسارات الموافقة في وضع report-only قبل الإنفاذ.
- أبقِ CMP في قائمة السماح الصريحة حتى لا تعطّله تغييرات CSP.