تسريب KV cache في Workers AI: إزاي HTTP 200 خبّى ردود مستخدمين تانيين
Cloudflare نشرت post-mortem لحادثة في موديل GLM-5.3 على Workers AI: 155 رد فيهم بيانات من requests تانية بسبب إعداد غلط وباج في SGLang. إيه اللي حصل واتصلّح إزاي.
تخيّل إنك بتبعت prompt طويل لموديل AI على cloud، والرد يرجعلك بـ HTTP 200 ومن غير أي error، بس جواه أجزاء من prompts مستخدمين تانيين. ده بالظبط اللي Cloudflare حكته في post-mortem نشرته يوم 26 أكتوبر عن موديل GLM-5.3 على Workers AI.
اللي حصل باختصار
حسب مدونة Cloudflare:
- 27 أغسطس: الموديل
@cf/zai-org/glm-5.3اتطلق على Workers AI، والمشكلة كانت موجودة من أول يوم - 8 سبتمبر: الباحث الأمني Gadi Evron من Knostic بلّغ عن طريق برنامج HackerOne إن الـ prompts الطويلة جدًا ساعات بترجّع نص تبع sessions مستخدمين تانيين
- 9 سبتمبر: Cloudflare أكدت المشكلة، وقفلت الموديل في خلال 40 دقيقة من إعلان الحادثة، ونزّلت config متصلّح ونسخة patched من الـ inference engine، والخدمة رجعت نفس اليوم
إجمالي الردود اللي اتأثرت 155 رد، وكلها كانت على prompts أطول من 681,280 token. Cloudflare بتقول إنها ملقتش دليل على استغلال متعمد، وإن مفيش أي موديل تاني على Workers AI اتأثر.
السبب الأول: إعداد غلط
الموديل اتنشر بـ context window معلن 1,048,576 token، بس الـ KV cache pool على GPUs الـ prefill كان فيه مكان لـ 681,280 token بس.
الفريق كان عارف الفرق ده قبل الإطلاق، بس افترض إن الـ engine هيرجّع error لأي prompt مش قادر يعالجه. اختبارات الـ long context كانت بتشيك على الـ HTTP status والأداء، ومكانتش بتشيك على محتوى الرد نفسه، فالـ 200 خلّاهم مطمّنين.
السبب التاني: باج في SGLang
Cloudflare بتستخدم SGLang (inference engine مفتوح المصدر) بطريقة disaggregated: GPUs للـ prefill بتعالج الـ prompt وتطلّع الـ KV cache، وبعدين تنقله لـ GPUs الـ decode اللي بتولّد الرد.
لما prompt أكبر من الـ pool كان بيوصل:
- الـ scheduler بيرفضه ويبدّله بـ placeholder من token واحد
- بس طوابير الـ admission في الـ prefill والـ decode كانت بتسأل «الـ request خلص؟» مش «اتّرفض؟»، فالـ request المرفوض كان بيعدّي على إنه شغال
- الـ decode كان حاجز صفحات KV على أساس طول الـ prompt الحقيقي، بس الـ prefill كتب صفحة واحدة بس
- باقي الصفحات كان فيها بقايا requests قبله، لأن الصفحات مش بتتصفّر بين الـ requests عشان الأداء
- النتيجة: رد بـ HTTP 200 بدل 400، فيه محتوى من مستخدمين تانيين
اتصلّح إزاي؟
- Cloudflare عدّلت الـ config بحيث الـ prefill KV pool بقى حوالي 2.04 مليون token، يعني تقريبًا ضعف الـ context length
- عملت patch للـ engine بحيث الـ request المرفوض يتقفل بالـ error بتاعه قبل أي حجز أو نقل KV، واقترحته upstream
- SGLang نزّلت الإصلاح في
v0.5.20مع متابعات فيv0.5.21وv0.5.22 - Cloudflare بقت تقارن حجم الـ KV pool بالـ context length من الـ engine الشغال قبل أي تغيير في الـ deployment
لو بتشغّل SGLang عندك، Cloudflare بتنصح بالتحديث لـ v0.5.22 أو أحدث:
pip install --upgrade "sglang>=0.5.22"
رأيي
الدرس هنا أكبر من الـ GPUs والـ inference. أي pipeline بيستخدم LLM ممكن يرجّع 200 وهو بيرجّع كلام غلط أو مش بتاعك. لازم الاختبارات تشيك على المحتوى نفسه، زي canary markers أو أسئلة إجابتها معروفة، مش على الـ status code بس. وبرضه احترام إن Cloudflare نشرت التفاصيل كلها بالأرقام والـ timeline بالتنسيق مع SGLang.
إنتوا بتختبروا ردود الـ LLM في الـ CI إزاي؟
المصادر
- AI
- Security
- Cloudflare
- LLM
- SGLang
- Inference