تخطَّ إلى المحتوى

🟧 شرح HTML

أمان الروابط والمحتوى المضمّن

الدرس 25 من 35· ⏱ 4 دقائق قراءة

لماذا يحتاج HTML "أمانًا" أصلًا؟

HTML نفسه لا يشغّل كودًا خطيرًا وحده، لكن طريقة استخدامه تفتح ثغرات حقيقية — خصوصًا حين تربط صفحتك بمصادر خارجية لا تتحكم بها: رابط لموقع آخر، إطار <iframe> مضمّن، أو حتى نص كتبه مستخدم آخر وعرضته على صفحتك. هذا الدرس يبني على الروابط والصور والوسائط المتعددة.

target="_blank" بحاجة إلى rel="noopener"

<!-- ⚠️ الرابط أدناه ثغرة أمنية معروفة -->
<a href="https://external-site.com" target="_blank">رابط خارجي</a>

<!-- ✅ الصيغة الآمنة -->
<a href="https://external-site.com" target="_blank" rel="noopener noreferrer">رابط خارجي</a>

حين يفتح رابط بـ target="_blank" بلا rel="noopener"، تحصل الصفحة الجديدة على وصول جزئي لكائن window الخاص بصفحتك الأصلية عبر window.opener — ويمكن نظريًا لصفحة خبيثة استغلال هذا لإعادة توجيه صفحتك الأصلية لموقع تصيّد (Tabnabbing) بينما أنت لا تزال تتصفح التبويب الجديد دون أن تلاحظ.

  • rel="noopener" يقطع هذا الوصول تمامًا.
  • rel="noreferrer" يضيف فوقها: لا يرسل ترويسة Referer (عنوان الصفحة التي جئت منها) للموقع الوجهة.
  • المتصفحات الحديثة تطبّق سلوك noopener تلقائيًا مع target="_blank"، لكن كتابته صراحة تبقى أفضل ممارسة موثّقة ومتوافقة مع كل الإصدارات.

🔑 قاعدة سريعة: أي target="_blank" تكتبه إلى رابط خارجي، أرفقه بـ rel="noopener noreferrer" دون تفكير إضافي.

تضمين محتوى لا تثق به تمامًا: <iframe sandbox>

في درس الوسائط رأينا <iframe> لتضمين YouTube وخرائط. حين يكون مصدر المحتوى المضمّن أقل ثقة — إعلان من طرف ثالث، أو معاينة كود يكتبها مستخدمك — استخدم خاصية sandbox:

<iframe
  src="https://untrusted-widget.example.com"
  sandbox="allow-scripts"
  title="ودجت خارجي">
</iframe>

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

القيمةما تسمح به
allow-scriptsتشغيل جافاسكريبت داخل الإطار
allow-formsإرسال نماذج من داخل الإطار
allow-popupsفتح نوافذ/تبويبات جديدة من الإطار
allow-same-originمعاملة الإطار كأنه من نفس مصدر صفحتك (احذرها مع محتوى لا تثق به)

خاصية أخرى مفيدة هي referrerpolicy="no-referrer" لمنع إرسال عنوان صفحتك للموقع المضمّن.

⚠️ لا تجمع أبدًا allow-scripts مع allow-same-origin على محتوى لا تثق به — الجمع بينهما يسمح للسكربت المضمّن بالتلاعب بصفحتك عبر DOM، وهو بالضبط ما يفترض أن يمنعه sandbox (راجع مرجع وسم iframe).

أخطر ثغرة تصنعها بنفسك: حقن HTML من مدخلات غير موثوقة

هذه أهم نقطة في الدرس. تخيّل صفحة تعليقات تعرض تعليق كل زائر مباشرة داخل الصفحة:

<!-- ❌ خطر: عرض نص المستخدم كـ HTML خام دون تنقية -->
<div class="comment"><!-- محتوى التعليق يُلصق هنا كما هو --></div>

لو كتب أحد الزوار تعليقًا يحتوي <script> أو معالج حدث مثل onerror، وعُرض نصّه كـ HTML خام بدلًا من نص عادي، سينفّذه متصفح كل زائر آخر يفتح الصفحة. هذا هجوم يُسمّى Cross-Site Scripting (XSS)، وهو من أكثر ثغرات الويب شيوعًا وخطورة — لكن يبدأ غالبًا من قرار HTML بسيط: "هل أعرض هذا النص كنص، أم كـ HTML؟"

القاعدة التي يوفّرها HTML/DOM نفسه:

  • عرض نص كمحتوى نصي عادي (textContent في جافاسكريبت، أو محرك القوالب الذي يهرّب الرموز تلقائيًا افتراضيًا) آمن دائمًا — أي < أو > يظهر كرمز حرفي، لا كوسم.
  • عرض نص كـ HTML خام (innerHTML في جافاسكريبت، أو أي دالة تسمّى صراحة "raw"/"unsafe"/"dangerouslySet...") يُنفَّذ ككود — استخدمه فقط لمحتوى تثق به 100%، أبدًا لمدخلات مستخدم مباشرة.

⚠️ HTML وحده لا يملك آلية "تنقية" — الحماية الفعلية تحدث في طبقة الخادم أو الإطار البرمجي الذي يبني الصفحة (تهريب الرموز الخاصة، أو قوائم سماح Sanitization). ما يمنحك إياه HTML هو فهم أين يكمن الخطر: أي مكان تُعامَل فيه مدخلات المستخدم كـ HTML بدل نص.

الاستخدام الواقعي

  • موقع تجارة إلكترونية يضع أزرار "شارك على" لمواقع خارجية بـ target="_blank" — يحتاج rel="noopener noreferrer" على كل واحد.
  • لوحة تحكّم تعرض معاينة كود HTML كتبه المستخدم (مثل محرر الأكواد في هذا الموقع) — تُعرض داخل <iframe sandbox> معزول، لا كـ HTML مباشر في الصفحة الرئيسية.
  • منتدى أو قسم تعليقات — نص التعليق يُعرض كنص مُهرَّب (escaped) دائمًا، لا كـ HTML خام.

الأخطاء الشائعة

  • target="_blank" بلا rel="noopener" على روابط خارجية — يبقى أشهر خطأ أمني بسيط في HTML.
  • ❌ الظن أن sandbox وحدها كافية بلا التفكير في القيم التي تضيفها فوقها — sandbox الفارغة مقيّدة جدًا وقد تكسر الودجت المضمّن إن لم تُرفق القيم الصحيحة.
  • ❌ عرض مدخلات المستخدم كـ HTML خام (innerHTML أو ما يعادلها) دون تفكير — أشهر سبب لثغرات XSS الحقيقية في الإنتاج.
  • ❌ افتراض أن HTML "آمن دائمًا" لأنه ليس لغة برمجة — القرارات حول كيفية عرض المحتوى الخارجي هي بالضبط ما يحدد الأمان.

خلاصة

كل رابط target="_blank" لموقع خارجي يحتاج rel="noopener noreferrer". كل <iframe> لمحتوى لا تثق به بالكامل يحتاج sandbox بأقل الصلاحيات الكافية لعمله. والقاعدة الأهم: نص المستخدم يُعرض كنص، لا كـ HTML خام، إلا إذا كنت تثق بمصدره تمامًا — فهذا هو الفرق بين صفحة عادية وصفحة قابلة للاختراق.

شرح أمان الروابط والمحتوى المضمّن — HTML بالعربي
أمان الروابط والمحتوى المضمّنHTML بالعربي · The Code Fix

📚 لمزيد من التعمّق في HTML، راجِع توثيق HTML على MDN.

هل كان هذا الدرس مفيدًا؟