الرابط لمرة واحدة الذي يُحذف عند أول طلب GET عادي يفقد قيمته لحظة يجلبه Slack أو Teams أو بوابة بريد إلكتروني لعرض معاينة. والحل أن تعيد البيانات الوصفية فقط عند GET، وأن تحذف السر نهائيًا عند طلب إظهار صريح عبر POST، مع عبارة مرور تُرسل عبر قناة ثانية كخط دفاع أخير. يشرح هذا المقال الأنظمة التي تجلب الروابط دون استئذان، وكيف تصمم بحيث لا يضرك أي منها.
بُني مولّد الروابط السرية لمرة واحدة في LinkPilot على هذا الأساس: طلب المعاينة لا يحصل إلا على هيكل الصفحة، ولا يُجلب السر ولا تُحتسب المشاهدة إلا حين يشغّل متصفح الصفحة.
نمط الفشل الافتراضي
تحاول معظم تطبيقات الدردشة والبريد الإلكتروني عرض معاينة حين ترى عنوان URL. ويجري الأمر هكذا:
- يلصق المستخدم الرابط السري في Slack.
- تجلب أداة المعاينة في Slack الرابط (ترسل
GET، وقد وثّق Slack هذا السلوك تحت عنوان link unfurling). - يتعامل معالج الإظهار لديك مع الطلب كأنه مشاهدة من إنسان، فيحذف السر نهائيًا ويعيد المحتوى.
- يستلم Slack المحتوى المحذوف (أو صفحة عامة) ويعرضه.
- ينقر الإنسان على الرابط، فيرى «تمت مشاهدته سابقًا»، ويراسل المرسل طالبًا رابطًا جديدًا.
لم تكن لدى أداة المعاينة نية سيئة. معالجك هو الذي خلط بين «أحدهم جلب الرابط» و«المستلم قرأ السر». هذان حدثان مختلفان، ومشكلة التصميم كلها في إبقائهما منفصلين.
وفي الخطوة 3 احتمال أسوأ: إذا تلقّى طلب GET من أداة المعاينة المحتوى الفعلي، فالسر الآن موجود داخل البنية التي يستخدمها طرف ثالث لإنشاء المعاينات. في أفضل الأحوال تخلّص منه بعد إنشاء المعاينة، لكن لا سبيل لك إلى تأكيد ذلك، ولا حدث في سجل التدقيق يخبرك بما جرى.
من يجلب الرابط قبل أن يفتحه المستلم؟
أدوات معاينة الروابط في تطبيقات الدردشة، وبوابات أمان البريد الإلكتروني، وبرامج حماية الأجهزة، وخوادم الوكيل في الشركات، وإضافات المعاينة في المتصفح، وفي العادة أكثر من واحد منها. عبارة «Slack يعرض معاينات» تقلل من حجم المشكلة. فالرابط الذي يُلصق في بيئة عمل حديثة تجلبه في العادة عدة أنظمة قبل أن ينقر عليه أي إنسان:
| الجهة التي تجلب الرابط | متى تعمل | هل يمكن التعرف عليها؟ |
|---|---|---|
| أدوات المعاينة في تطبيقات الدردشة (Slack و Teams و iMessage و WhatsApp و LinkedIn) | لحظة إرسال الرسالة | في العادة نعم، فلها وكلاء مستخدم مميزون مثل Slackbot-LinkExpanding |
| بوابات أمان البريد الإلكتروني (Mimecast و Proofpoint و Microsoft Defender) | عند التسليم، وكثيرًا ما تعود عند النقر | في الغالب لا، فكثير منها يقدّم وكلاء مستخدم لمتصفحات حقيقية |
| حماية الأجهزة / برامج مكافحة الفيروسات | حين يصل الرابط إلى جهاز المستلم | نادرًا |
| خوادم الوكيل في الشركات | عند النقر، قبل تمرير طلب المستخدم | نادرًا |
| إضافات المتصفح لمعاينة الروابط | عند تمرير المؤشر أو تحميل الصفحة | لا، فهي تعمل داخل جلسة متصفح المستخدم نفسه |
سلوك المزودين في هذا الجدول يتغير باستمرار، فتعامل مع ما يُذكر عن بوابة بعينها على أنه «كما نُشر في يوليو 2026، ويجب التحقق منه في الوثائق الحالية». لكن العامل المشترك ثابت: كل هذه الأنظمة ترسل طلب GET عاديًا، لأنه الطريقة الآمنة والعامة الوحيدة للاطلاع على رابط لا تتحكم فيه.
كيف تمنع المعاينة من حذف الرابط لمرة واحدة؟
أعد البيانات الوصفية عند GET، ولا تحذف السر إلا عند POST صريح. دلالات HTTP تتيح ذلك أصلًا: يعرّف RFC 9110، القسم 9.2.1 طلب GET بأنه آمن ومتساوي الأثر (idempotent)، أي طلب يحق لأي أحد إرساله بحرية لأنه لا يُفترض أن يغيّر شيئًا. أما POST فهو فعل التنفيذ. لذا اجعل الإظهار إجراء POST خلف زر ظاهر:
GET /s/abc123 → HTML page: "Click to reveal this secret"
POST /s/abc123 → burns the secret, returns the payload
الآن يعيد طلب GET من Slack صفحة بيانات وصفية محايدة، ولا يُحذف السر إلا حين ينقر الإنسان على الزر. وأي أداة فحص تحترم دلالات HTTP لا تقترب من المحتوى أبدًا، وهذا يشمل جميعها تقريبًا، لأن إرسال طلبات POST ذات آثار جانبية إلى روابط عشوائية سيعطّل نصف الويب.
تتبّع عملي خطوة بخطوة
تابع رابطًا واحدًا من البداية إلى النهاية. تنشئ سرًا مع الحذف بعد القراءة وعبارة مرور، ثم تلصق الرابط في رسالة مباشرة على Slack وفي رسالة بريد إلكتروني.
- أداة المعاينة في Slack ترسل
GET /s/abc123. الاستجابة: صفحة بيانات وصفية صغيرة، الحالة «active» (نشط) وعبارة المرور مطلوبة. لا تُسجَّل أي مشاهدة، والسر باقٍ. - بوابة البريد الإلكتروني لدى المستلم تعيد كتابة الرابط في الرسالة وتجلبه عند التسليم لتحليل سمعته. الطلب
GETنفسه والبيانات الوصفية نفسها. والسر ما زال باقيًا. - ينقر المستلم على الرابط في الرسالة. تجلب أداة الفحص في البوابة الرابط مرة أخرى عند النقر (
GET)، ثم توجّه المتصفح إلى وجهته. - يحمّل المتصفح صفحة الإظهار بطلب
GETآخر. تعرض الصفحة زر إظهار وحقلًا لعبارة المرور، ولم تُسجَّل أي مشاهدة بعد. - يُدخل المستلم عبارة المرور وينقر على زر الإظهار. يرسل المتصفح
POST /s/abc123، فتُسجَّل المشاهدة ويُعاد المحتوى ويُحذف السر نهائيًا. - كل من يجلب الرابط بعد ذلك يحصل على استجابة صريحة تفيد بأنه «شوهد وحُذف نهائيًا» بدل المحتوى.
خمسة طلبات جلب، وإظهار واحد. هذه النسبة طبيعية في بيئة الشركات، وأي تصميم لا يحتملها سيفشل من اليوم الأول، وعندها سيلصق المرسل كلمة المرور في الدردشة مباشرة.
طبقات الحماية
الفصل بين GET و POST
يتعامل مع كل أدوات المعاينة والفحص المنضبطة، وهي الغالبية الساحقة من الحركة الآلية. هذا هو الأساس، وكل ما يلي طبقات إضافية.
اشتراط عبارة مرور
تغطي عبارة المرور ما لا يغطيه الفصل: بيئات الاختبار المعزولة التي تشغّل JavaScript وتتفاعل مع الصفحة، إضافة إلى النقرات البشرية العارضة والرسائل المُعاد توجيهها. تستطيع بيئة الاختبار المعزولة أن تنقر على زر الإظهار، لكنها لا تستطيع أن تقدّم عبارة مرور وصلت عبر قناة أخرى. أرسل الرابط بالبريد الإلكتروني وعبارة المرور برسالة مباشرة على Slack أو برسالة SMS.
تصفية الروبوتات حسب وكيل المستخدم
استبعد روبوتات المعاينة المعروفة (Slackbot و LinkedInBot و Twitterbot) قبل أن تصل إلى أي منطق للإظهار. هذا إجراء احتياطي يستحق التطبيق، لكنه لا يكفي وحده أبدًا: أدوات الفحص الأمني تقدّم عادةً وكلاء مستخدم لمتصفحات حقيقية، والغرض من ذلك تحديدًا ألا تتمكن الصفحات الخبيثة من التخفي عن التحليل.
صلاحية قصيرة
قلّص المدة التي يمكن أن يقع فيها الضرر. الرابط الذي لم تتجاوز صلاحيته خمس عشرة دقيقة يترك في أدوات الفحص وملفات السجلات وسجل الدردشة عنوانًا لم يعد يؤدي إلى أي شيء.
Cache-Control: no-store
اضبطه على كل استجابة إظهار حتى لا يحتفظ أي وسيط، سواء خادم وكيل في الشركة أو شبكة CDN أو ذاكرة التخزين المؤقت في المتصفح، بنسخة من المحتوى بعد القراءة المشروعة الوحيدة.
بوابات أمان البريد الإلكتروني تحديدًا
تستحق بوابات الشركات قسمًا خاصًا لأنها تجلب الرابط مرتين. فالمنتجات من هذه الفئة (وMicrosoft Defender Safe Links هو المثال الموثّق) تعيد كتابة كل رابط في البريد الوارد ليمر عبر نطاق الفحص الخاص بها. وفي العادة يُجلب الرابط مرة عند التسليم لتحليل سمعته، ومرة أخرى عند النقر، قبل توجيه الإنسان إلى الوجهة الحقيقية.
لو كان أي من الطلبين يحذف السر، لرأى المستلم رابطًا معطلًا في كل مرة، وهو فشل يبدو عشوائيًا للمستخدمين لكنه محدد تمامًا. يستوعب الفصل بين GET و POST الطلبين دون أي كلفة، لأن كليهما طلب GET عادي. ثم يوصل التوجيه عند النقر الإنسان إلى صفحة الإظهار، حيث يجري طلب POST.
حالات حدّية ما زالت مؤذية
- بيئات الاختبار المعزولة التي تشغّل JavaScript. بعض هذه البيئات تعرض الصفحة وتتفاعل معها. ونظريًا، قد تنقر بيئة عدوانية على زر يرسل
POSTإن لم تكن هناك عبارة مرور. وعبارة المرور هي خط الدفاع الأخير. - الرابط وعبارة المرور في القناة نفسها. إذا وصلا معًا في رسالة بريد واحدة، لا يبقى من كل الحمايات السابقة إلا الأمل في ألا يقرأ أحد تلك الرسالة. افصل القنوات دائمًا.
- إعادة التوجيه. كل إعادة توجيه إلى تطبيق دردشة أو نظام بريد جديد تطلق جولة جديدة من المعاينات. لا ضرر من ذلك مع الفصل، لكن كل محطة تضيف مجموعة أخرى من السجلات تحتفظ بالرابط، وهذه حجة لصالح الصلاحية القصيرة.
- الإظهار المتزامن. إذا نقر شخصان على زر الإظهار في الوقت نفسه، يجب أن تجري القراءة والحذف في خطوة واحدة لا تتجزأ: طلب واحد بالضبط ينجح، والآخر يحصل على «تمت مشاهدته سابقًا». أما التنفيذ الذي يفصل بين الخطوتين فقد يعرض المحتوى مرتين.
اختبر أداتك بنفسك
قبل أن تأتمن أي خدمة لمشاركة الأسرار على بيانات دخول حقيقية، أجرِ هذا الفحص الذي يستغرق دقيقتين:
- أنشئ سرًا للتجربة مع تفعيل الحذف بعد القراءة.
- اجلبه من الطرفية، وهذا بالضبط ما تفعله أداة المعاينة:
curl -s -o /dev/null -w "%{http_code}" "<url>" - افتح الرابط في متصفح. إن رأيت «تمت مشاهدته سابقًا»، فالأداة تحذف السر عند
GET، وليس من الآمن لصق روابطها في الدردشة أو البريد الإلكتروني. - إن بقي السر، فأظهره بالطريقة الصحيحة في المتصفح، ثم شغّل
curlمرة أخرى. ينبغي أن تحصل الآن على استجابة صريحة تفيد بأن السر لم يعد موجودًا أو حُذف نهائيًا، لا على المحتوى.
كيف يطبّق LinkPilot هذا التصميم
للتوثيق، هذا هو التصميم الذي تستخدمه الروابط السرية في LinkPilot: طلب GET على نقطة الإظهار يعيد البيانات الوصفية فقط (الحالة، وهل عبارة المرور مطلوبة)، ولا تُسجَّل المشاهدة إلا عند إظهار صريح عبر POST. تُجزَّأ عبارات المرور بخوارزمية SHA-256 على جهاز المستخدم، ويُحدّ عدد المحاولات بخمس في الدقيقة لكل عنوان IP ولكل سر. وتحمل كل استجابة إظهار الترويسة Cache-Control: no-store، والأسرار المحذوفة نهائيًا أو المنتهية صلاحيتها تعيد رمز HTTP 410 بعد الكتابة فوق المحتوى المخزن، ويسجّل سجل التدقيق كل حدث مع قيمة تجزئة لعنوان IP باستخدام ملح يتغير يوميًا، أما عنوان IP الخام فلا يُخزَّن أبدًا. التفاصيل الكاملة في صفحة البنية الأمنية.
جرّبها مجانًا، بدون تسجيل
رسالة ذاتية التدمير
أرسل ملاحظة تختفي بعد قراءتها مرة واحدة.
حدود هذا التصميم
لنكن صريحين بشأن الحدود: لا شيء مما سبق يحمي السر بعد إظهار مشروع، فالمستلم يستطيع نسخ المحتوى نفسه أو التقاط صورة للشاشة أو إعادة توجيهه. ولا يفيد التصميم إذا أُرسلت عبارة المرور مع الرابط. ولا يستطيع أن يمنع شخصًا أُرسل إليه الرابط خطأً من فتحه قبل المستلم المقصود، ولهذا وُجد سجل التدقيق: ترى المشاهدة غير المتوقعة، فتغيّر بيانات الدخول.
قراءات ذات صلة
المراجع
- IETF، RFC 9110: HTTP Semantics, section 9.2.1 Safe Methods.
- Slack API، Unfurling links in messages.
- Microsoft Learn، Safe Links in Microsoft Defender for Office 365.
