Laravel 13.40.0: تغييرات في المعاملات والنسخ المتماثلة وRedis ينبغي اختبارها أولًا
إصدار فرعي يغيّر سلوك تطبيقات Laravel كثيفة الاعتماد على قواعد البيانات عند الأعطال، إضافةً إلى إصلاح ذي طابع أمني في Concurrency صدر دون أي نشرة أمنية.
تحليل هندسي آلي من مكتب خالد أبوبكر الهندسي، مبني على المصادر الأولية المذكورة أدناه. لم يراجعه شخص قبل النشر. عن المكتب
الخلاصة
يتضمن Laravel v13.40.0 إصلاحًا يضيف مصادقة لمغلّف نتائج عمليات Concurrency للحماية من حقن مخرجات المهام، لكن لم تُنشر أي نشرة أمنية أو درجة خطورة أو نطاق للإصدارات المتأثرة. كما أن تغييراته في إعادة الاتصال أثناء المعاملات والتراجع إلى نقاط الحفظ تبدّل سلوك مسارات الفشل في التطبيقات كثيفة الاعتماد على قواعد البيانات. ينبغي للفرق العاملة على 13.x تمرير الترقية عبر بيئة الاختبار المرحلي دون إبطاء، واختبار مسارات المعاملات وإعادة المحاولة، ومنحها الأولوية إن كانت تستخدم ميزة Concurrency.
ماذا حدث
نشر Laravel إصدار إطار العمل v13.40.0 على الفرع 13.x. ويمسّ عدد من التغييرات المدرجة سلوك قاعدة البيانات والذاكرة المؤقتة عند الأعطال أو تحت الأحمال:
- إعادة الاتصال أثناء المعاملة (#62211): بات إطار العمل يعيد الاتصال بعد فقدان الاتصال بقاعدة البيانات أثناء معاملة.
- التراجع إلى نقطة حفظ (#62248): أصبحت المعاملات المتداخلة تتراجع إلى نقطة حفظ (savepoint) عند أخطاء التزامن.
- اتصال الكتابة في
createOrFirst(#62223): صار البحث فيcreateOrFirstالخاص بـBelongsToManyيستخدم اتصال الكتابة. - تفريغ الذاكرة المؤقتة الموسومة في Redis (#62215): لم يعد تفريغ عدد كبير من وسوم الذاكرة المؤقتة يحجب (block) خادم Redis.
- لحاق القراءة بالكتابة (#62198): أساس جديد في طبقة قاعدة البيانات لتحديد ما إذا كان اتصال القراءة قد لحق باتصال الكتابة.
- تحديث مسارات JSON (#62225): إصلاح لتحديث مسارات JSON باستخدام المصفوفات والمجموعات (collections) على MySQL وMariaDB.
- مغلّف Concurrency (#62297): تغيير يضيف مصادقة لمغلّف نتائج عمليات Concurrency «لمنع حقن مخرجات المهام».
لا تتضمن ملاحظات الإصدار سوى عناوين طلبات الدمج (PR)، ولا تذكر أي نشرة أمنية أو CVE أو درجة خطورة أو نطاق للإصدارات المتأثرة بخصوص #62297.
لماذا يهم
يستحق هذا الإصدار أكثر من مجرد composer update روتيني في التطبيقات كثيفة الاعتماد على قواعد البيانات. فاثنان من التغييرات (#62211 و#62248) يبدّلان ما يحدث في مسار فشل المعاملة: انقطاع الاتصال وأخطاء التزامن. ونادرًا ما تغطي الاختبارات هذه المسارات، وفيها تميل أخطاء سلامة البيانات إلى الاختباء.
أما بقية بنود قاعدة البيانات فتهم بنى (topologies) بعينها:
- تتأثر التطبيقات التي تفصل القراءة عن الكتابة باستخدام نسخ متماثلة (replicas) بالتغيير #62223. والدافع الأرجح أن البحث في
createOrFirstعلى نسخة متماثلة متأخرة قد يفوّت صفًا موجودًا أصلًا في الخادم الرئيسي؛ ولا تذكر الملاحظات السبب. - يضع #62198 الأساس للوعي بتأخر النسخ المتماثلة. ولا تصف الملاحظات أي API عامة، لذا لا يصح البناء عليه بعد.
- تستفيد التطبيقات التي تستخدم وسوم ذاكرة Redis المؤقتة على نطاق واسع من #62215، لأن حجب نسخة Redis قد يعطّل مستهلكين آخرين يتشاركونها، لا الذاكرة المؤقتة وحدها.
- يحصل مستخدمو MySQL وMariaDB الذين يحدّثون أعمدة JSON بمصفوفات أو مجموعات على إصلاح (#62225).
والبند الأكثر عرضة للإغفال هو #62297. يصف عنوانه مصادقة بيانات تعبر حدود العمليات (process boundary) لمنع حقن المخرجات. هذه لغة التحصين الأمني، ومع ذلك يظهر سطرًا عاديًا في سجل التغييرات.
التقييم الهندسي
تقييمنا: ينبغي التعامل مع v13.40.0 بوصفه إصدارًا يحمل تغييرات دلالية في طبقة قاعدة البيانات، لا تصحيحًا شكليًا. ومرّر الترقية عبر بيئة الاختبار المرحلي (staging) بدلًا من نقلها مباشرة إلى الإنتاج.
إعادة الاتصال أثناء المعاملة (#62211) هي التغيير الأجدر بالتدقيق. إعادة الاتصال داخل معاملة أمر دقيق: فعند انقطاع الاتصال تضيع المعاملة على جانب الخادم ومعها العمل غير المُثبَّت (uncommitted). ولا يوضح عنوان طلب الدمج:
- ما إذا كان إطار العمل يعيد الآن تنفيذ دالة المعاملة (callback)؛
- ما إذا كان يُطلق استثناءً بعد إعادة الاتصال؛
- كيف يتعامل مع العمل الذي نُفّذ قبل الانقطاع.
وإلى أن يُقرأ طلب الدمج نفسه، افترض أن الشيفرة التي تعتمد على انتشار استثناء فقدان الاتصال خارج DB::transaction() قد تشهد سلوكًا مختلفًا. ويشمل ذلك أغلفة إعادة المحاولة المخصصة، ومنطق إعادة محاولة مهام الطوابير، وضمانات عدم التكرار (idempotency). وبشكل منفصل، يوسّع #62270، الذي يعامل QueryList.TerminateAll() على أنه فقدان للاتصال، مجموعةَ الأخطاء التي تُحتسب فقدانًا للاتصال.
التراجع إلى نقطة حفظ (#62248) يغيّر حالة المعاملة الخارجية بعد فشل داخلي. إذا واجهت معاملة داخلية خطأ تزامن (والأرجح حالات الجمود deadlocks أو إخفاقات التسلسل serialisation failures؛ ولا تحدد الملاحظات ذلك)، فإن التراجع إلى نقطة حفظ يهدف إلى إبقاء المعاملة الخارجية حية. قد يكون ذلك مفيدًا، لكن الشيفرة التي افترضت أن المعاملة بأكملها قد انتهت، فأعادت المحاولة من البداية، قد تتصرف الآن بشكل مختلف. وقد يتوقف بقاء المعاملة الخارجية صالحة للاستخدام بعد مثل هذا الخطأ على محرك قاعدة البيانات، لذا اختبر على المحرك الذي تشغّله فعلًا، لا على SQLite في خط التكامل المستمر.
استخدام اتصال الكتابة في createOrFirst (#62223) هو على الأرجح إصلاح لصحة السلوك. ويُرجَّح أنه يعالج حالة تسابق (race) قد يُفشل فيها تأخرُ النسخة المتماثلة نمطَ «الإنشاء أو البحث». توقّع بعض حمل القراءة الإضافي على الخادم الرئيسي في مسار الشيفرة هذا؛ وحجم هذا الأثر غير مُتحقَّق منه ويستحق القياس في بنيتك.
إصلاح تفريغ وسوم Redis (#62215) تحسين تشغيلي. ويستحق الأخذ به إن كنت تفرّغ مجموعات وسوم كبيرة. ولا تذكر الملاحظات كيف يُنفَّذ التفريغ الآن، لذا راقب زمن الاستجابة واستهلاك الذاكرة في Redis بعد النشر.
لا ينبغي الاستخفاف بإصلاح مغلّف Concurrency (#62297). فلا نشرة أمنية له، ولا يعرف فريق التحرير ما إذا كان يعالج ثغرة أمنية قابلة للاستغلال ولا أي الإصدارات متأثرة. ويوحي عنوانه بأن مغلّف النتائج لم يكن مُصادَقًا قبل هذا الإصدار، أو لم يكن مُصادَقًا بشكل كافٍ؛ ولا تذكر الملاحظات أيّهما. وعلى أي فريق يستخدم ميزة Concurrency القائمة على العمليات أن يعامل الترقية على أنها ذات صلة بالأمن إلى أن يقول Laravel خلاف ذلك. فغياب النشرة الأمنية ليس دليلًا على انخفاض الخطورة.
لا شيء هنا يغيّر التوصيات الأوسع بشأن Laravel، لكنه يعزز إحداها: مكان سلوك مسارات الفشل هو اختبارات التكامل على قاعدة بيانات حقيقية.
هل يعنيك هذا؟
- تشغّل
laravel/frameworkعلى 13.x بإصدار أقدم من v13.40.0. تحقّق باستخدامcomposer show laravel/framework. - تغلّف العمل داخل
DB::transaction()وتعتمد على استثناءات فقدان الاتصال أو على منطق إعادة محاولة مخصص. - تستخدم معاملات متداخلة وتعالج حالات الجمود أو أخطاء التزامن الأخرى.
- تهيّئ اتصالات منفصلة للقراءة والكتابة وتستدعي
createOrFirstعلى علاقاتBelongsToMany. - تستخدم وسوم ذاكرة Redis المؤقتة وتفرّغ عددًا كبيرًا من الوسوم دفعة واحدة.
- تحدّث أعمدة JSON بمصفوفات أو مجموعات على MySQL أو MariaDB.
- تستخدم ميزة Concurrency في Laravel مع عمليات فرعية (child processes).
- تعمل على إصدار رئيسي أقدم من Laravel. فالأدلة لا تغطي إلا 13.x، ولا يُذكر أي نقل للإصلاحات إلى فروع أقدم (backport).
ما الذي ينبغي فعله
- الجرد. شغّل
composer show laravel/frameworkفي كل تطبيق وسجّل إصدار 13.x المنشور. - امنح الأولوية لمستخدمي Concurrency. إن كنت تستخدم ميزة Concurrency، فجدول الانتقال إلى v13.40.0 أولًا:
composer update laravel/framework، ثم انشر عبر بيئة الاختبار المرحلي. افعل ذلك رغم عدم وجود نشرة أمنية. - اختبر مسارات الفشل في بيئة الاختبار المرحلي على محرك قاعدة البيانات الذي تستخدمه فعلًا:
- اقطع الاتصال بقاعدة البيانات في منتصف معاملة وتأكد مما تلاحظه شيفرتك الآن.
- افتعل حالات جمود في معاملات متداخلة وتحقق مما إذا كان العمل الخارجي يُحفظ أم يُعاد تنفيذه.
- أعد تشغيل أي اختبارات لأغلفة إعادة المحاولة وعدم التكرار.
- إعدادات النسخ المتماثلة. تأكد من أن
createOrFirstعلىBelongsToManyيعمل بشكل صحيح، وقِس أي تغيير في حمل الخادم الرئيسي. - Redis. بعد النشر، راقب زمن الاستجابة والذاكرة في Redis أثناء عمليات تفريغ الوسوم الكبيرة.
- اقرأ طلبات الدمج قبل الاعتماد على السلوك الجديد. ينطبق هذا خصوصًا على #62211 و#62248 و#62297، لأن ملاحظات الإصدار لا تتضمن سوى العناوين.
- ثبّت الإصدار وراقب (ليس توجيهًا من المورّد). ثبّت الإصدار الدقيق لإطار العمل في
composer.lock. انشر أولًا في بيئة canary أو بيئة منخفضة الحركة، مع تنبيهات على معدلات استثناءات قاعدة البيانات.
الفرق التي تبني منصات ويب على Laravel مع نسخ متماثلة للقراءة وRedis هي الأكثر تعرضًا لهذه التغييرات.
ما لا نعرفه بعد
- ما إذا كان #62297 يصلح ثغرة أمنية، وأي الإصدارات السابقة متأثرة، ومدى خطورتها. لا توجد نشرة أمنية ولا CVE.
- كيف يتصرف #62211 بالضبط بعد إعادة الاتصال، وكيف يتفاعل كلٌّ من #62211 و#62248 مع منطق إعادة المحاولة القائم.
- ما إذا كان أي تغيير غير متوافق مع الإصدارات السابقة بالنسبة إلى التطبيقات العاملة على إصدارات 13.x الأقدم.
- أيٌّ من إصلاحات MySQL وMariaDB وPostgreSQL وRedis يمسّ صحة البيانات في التطبيقات القائمة، لا الحالات الطرفية فحسب.
- ما إذا كان أيٌّ من هذه الإصلاحات قد نُقل إلى فروع Laravel الأقدم المدعومة.
سيتحقق فريق التحرير من صدور نشرة أمنية من Laravel تغطي #62297، وسيراجع طلبات الدمج المرتبطة للاطلاع على تفاصيل السلوك. وستُنشر التحديثات على صفحة أخبار Engineering Desk.
المصادر
أحدث التحليلات الهندسية
قراءة 2 دقيقة
مكتبات SD-JWT لـ JavaScript تُسقط الإفصاحات المُعدَّلة بصمت وتُبلغ بالنجاح (CVE-2026-62374)
فجوة في المطابقة للمواصفة من جهة المُتحقِّق في مكتبات SD-JWT لـ JavaScript التابعة لـ OpenWallet Foundation تتيح لحامل بيانات الاعتماد حذف مطالبة (claim) بصمت، ولا يمنع ربط المفتاح ذلك.
قراءة 2 دقيقة
Stanza 1.14.0 يعيد فتح ثغرة تنفيذ تعليمات برمجية عبر pickle لا يستطيع weights_only=True منعها
الترقية إلى ما بعد Stanza 1.12.2 أغلقت مسارًا واحدًا لتنفيذ التعليمات البرمجية عبر pickle، لكن 1.14.0 أضاف مسارًا ثانيًا في lemmatizer لا يراه weights_only=True، ويُصلحه الإصدار 1.15.0.
قراءة 2 دقيقة
ثغرة CVE-2026-119084 في Amazon Redshift JDBC Driver: تحميل غير آمن للأصناف، والتصحيح في الإصدار 2.3.0
أصلحت AWS ثغرة انعكاس غير آمن (unsafe reflection) في Amazon Redshift JDBC Driver ضمن الإصدار 2.3.0. لكن درجة التعرض تتوقف على من يتحكم في سلاسل الاتصال لديك، وعلى ما يوجد في مسار الأصناف (classpath).