
مختبر Docker محلي لإعادة إنتاج CVE-2026-55255، وهي ثغرة من نوع IDOR في واجهة برمجة التطبيقات Responses في Langflow. يتحقق من تنفيذ التدفق عبر المستخدمين في الإصدارات الضعيفة مقابل المُصححة باستخدام PoC قائم على الطلبات.
/api/v1/responsesيحتوي هذا المستودع على معمل Docker محلي لإعادة إنتاج والتحقق من صحة CVE-2026-55255، وهي ثغرة مرجع كائن مباشر غير آمن (IDOR) تؤثر على واجهة برمجة تطبيقات Responses المتوافقة مع OpenAI في Langflow.
Langflow هي منصة مفتوحة المصدر لبناء ونشر الوكلاء وسير العمل المدعومين بالذكاء الاصطناعي. يؤثر السلوك الضعيف على نقطة النهاية /api/v1/responses، حيث يمكن لمهاجم مصادق تقديم UUID لتدفق مستخدم آخر كقيمة model ويتسبب في تنفيذ Langflow لذلك التدفق المملوك للضحية.
يقارن هذا المعمل بين إصدارين من Langflow:
| الخدمة | إصدار Langflow | الغرض | الرابط |
|---|---|---|---|
| vuln | 1.9.0 | هدف المقارنة الضعيف | http://localhost:7860 |
| patched | 1.9.1 | هدف المقارنة المصحح | http://localhost:7861 |
مسار التحقق من HTTP الموضح في هذا المعمل المحلي هو:```text Authenticated attacker API key → POST /api/v1/responses → request body sets model to victim-owned flow UUID → vulnerable target executes the victim-owned flow → patched target returns flow_not_found and does not execute the victim-owned flow
في الهدف الضعيف، يمكن لمفتاح API المملوك للمهاجم تنفيذ التدفق المملوك للضحية ويحتوي الرد على علامة خاصة بالضحية فقط:```text
VICTIM_ONLY_CONTEXT_55255_VULN
في الهدف المُصحَّح، لا يعيد نفس الطلب عبر المستخدمين علامة الضحية ويعيد نص خطأ على نمط OpenAI:```json {"error":{"message":"Flow with id '' not found","type":"invalid_request_error","code":"flow_not_found"}}
يختبر هذا المعمل سلوك HTTP بين الإصدار الضعيف والإصدار المصحح باستخدام Langflow 1.9.0 و Langflow 1.9.1.
يقتصر نطاق هذا المعمل عمداً على خدمات Docker المحلية. لا يستهدف أنظمة خارجية ولا يتضمن سرقة بيانات الاعتماد، أو تفريغ قواعد البيانات، أو الحمولات التدميرية، أو الاستدعاءات الخارجية، أو البرامج الضارة، أو الثبات، أو أنشطة ما بعد الاستغلال.
## Verified Facts
| الادعاء | الدليل | كيفية التحقق في هذا المعمل |
| ----- | -------- | ------------------------- |
| يؤثر CVE-2026-55255 على نقطة النهاية `/api/v1/responses` في Langflow. | يصف تنبيه GitHub GHSA-qrpv-q767-xqq2 IDOR في `/api/v1/responses`. | راجع قسم المراجع وشغّل PoC ضد كلا الهدفين المحليين. |
| يسرد تنبيه GitHub الإصدارات المتأثرة كـ `< 1.9.1` والإصدار المصحح كـ `1.9.1`. | تنبيه GitHub GHSA-qrpv-q767-xqq2. | قارن إصدارات الهدف الضعيف والهدف المصحح في `docker-compose.yml`. |
| تختلف بعض مصادر الثغرات الأمنية الفرعية حول الإصدار المصحح بالضبط. | تدرج GitHub/GitLab `1.9.1` كمصحَّح؛ تذكر بعض صفحات الاستخبارات الفرعية `1.9.2` أو تحتوي على صياغة مختلطة. | راجع قسم المراجع واعتمد على التحقق من المعمل لسلوك الإصدار 1.9.1 المُختبر. |
| يستخدم هذا المعمل Langflow 1.9.0 كهدف مقارنة ضعيف. | تستخدم خدمة `vuln` `langflowai/langflow:1.9.0`. | افحص `docker-compose.yml` وشغّل `docker compose ps`. |
| يستخدم هذا المعمل Langflow 1.9.1 كهدف مقارنة مصحح. | تستخدم خدمة `patched` `langflowai/langflow:1.9.1`. | افحص `docker-compose.yml` وشغّل `docker compose ps`. |
| تستخدم واجهة برمجة تطبيقات الاستجابات في Langflow `POST /api/v1/responses`. | يصف توثيق Langflow نقطة نهاية واجهة برمجة تطبيقات الاستجابات المتوافقة مع OpenAI. | شغّل PoC أو طلب curl يدوي ضد `/api/v1/responses`. |
| تقبل واجهة برمجة تطبيقات الاستجابات في Langflow معرف التدفق (flow ID) كقيمة `model`. | ينص توثيق Langflow على أن قيمة `model` تُستبدل بـ `flow_id`. | افحص نص طلب PoC. |
| تتطلب طلبات واجهة برمجة تطبيقات Langflow مفتاح API عبر `x-api-key`. | يصف توثيق واجهة برمجة تطبيقات Langflow المصادقة بمفتاح API عبر الرأس `x-api-key`. | افحص رؤوس طلب PoC. |
| يعتمد PoC على الطلبات. | يرسل `poc/validate_idor.py` طلبات HTTP ولا يستدعي Docker أو Docker Compose أو أوامر shell أو واجهات برمجة تطبيقات الحاويات. | افحص `poc/validate_idor.py`. |
| ينفذ الهدف الضعيف تدفقاً مملوكاً للضحية باستخدام مفتاح API مملوك للمهاجم. | يرد الاستجابة الضعيفة بـ `VICTIM_ONLY_CONTEXT_55255_VULN`. | شغّل أمر PoC الضعيف باستخدام معرف تدفق الضحية ومفتاح API للمهاجم. |
| يمنع الهدف المصحح نفس مسار التنفيذ عبر المستخدمين. | يرد الاستجابة المصححة بـ `error.code = flow_not_found` ولا تُرجع علامة الضحية. | شغّل أمر PoC المصحح باستخدام معرف تدفق الضحية ومفتاح API للمهاجم. |
## Assumptions and Unknowns
يستخدم هذا المعمل Langflow 1.9.0 كهدف مقارنة ضعيف لأن تنبيه GitHub GHSA-qrpv-q767-xqq2 يُحدد الإصدارات قبل 1.9.1 كمتأثرة، وأكد الاختبار المحلي السلوك الضعيف في 1.9.0.
يستخدم هذا المعمل Langflow 1.9.1 كهدف مقارنة مصحح لأن تنبيه GitHub GHSA-qrpv-q767-xqq2 يسرد 1.9.1 كإصدار مصحح، وأكد الاختبار المحلي أن 1.9.1 يمنع مسار التنفيذ عبر المستخدمين المُختبر `/api/v1/responses` مع `flow_not_found`.
هناك تباين في الإصدارات بين المصادر. تسرد تنبيهات GitHub و GitLab الإصدارات قبل 1.9.1 كمتأثرة و 1.9.1 كمصحح. تذكر بعض صفحات استخبارات الثغرات الأمنية الفرعية 1.9.2 أو تحتوي على صياغة مختلطة حول الإصدار المصحح. يوثق هذا المستودع ذلك التباين ويتحقق من السلوك المُختبر مباشرة:```text
Langflow 1.9.0
→ attacker API key + victim flow UUID
→ victim marker returned
→ vulnerable behavior observed
Langflow 1.9.1
→ attacker API key + victim flow UUID
→ flow_not_found
→ victim marker not returned
→ blocked behavior observed
يفترض هذا المعمل أن المهاجم يعرف بالفعل UUID لتدفق الضحية. لا يقوم إثبات المفهوم (PoC) بتخمين معرفات التدفق (flow IDs) بالقوة، ولا بتعداد التدفقات، أو بمحاولة اكتشاف معرفات تدفق الضحية.
يركز هذا المعمل على سلوك HTTP القابل للملاحظة لـ:```text POST /api/v1/responses
بشكل هذا الطلب:```json
{
"model": "<victim-flow-id>",
"input": "cross-user CVE-2026-55255 validation request",
"stream": false
}
المختبر يوضح تنفيذ التدفق عبر المستخدم غير المصرح به في الهدف الضعيف والسلوك المحظور في الهدف المصحح.
لا يوضح المختبر:
السبب الجذري لـ CVE-2026-55255 هو فجوة في التفويض في منطق حل التدفق في Langflow.
يقبل نقطة النهاية /api/v1/responses معرّف التدفق (UUID) من خلال حقل model. في الإصدارات الضعيفة، يمكن لمسار البحث عن UUID داخل get_flow_by_id_or_endpoint_name() تحميل كائن Flow مباشرة بواسطة المفتاح الأساسي دون فرض تطابق Flow.user_id المحلول مع مستخدم مفتاح API المصادق عليه.
يمكن تلخيص السلوك الضعيف على النحو التالي:```text Attacker owns API key → attacker sends POST /api/v1/responses → model contains victim-owned flow UUID → flow resolver loads Flow by UUID → resolver does not enforce Flow.user_id == attacker_user.id → response endpoint executes the victim-owned flow → attacker receives victim flow output
يمكن تلخيص السلوك المصحح على النحو التالي:```text
Attacker owns API key
→ attacker sends POST /api/v1/responses
→ model contains victim-owned flow UUID
→ flow resolver loads candidate Flow
→ resolver compares Flow.user_id with authenticated API-key user id
→ cross-user lookup is treated as not found
→ response endpoint returns flow_not_found
→ victim-owned flow is not executed
المشكلة الأمنية ليست في قدرة المهاجم على استدعاء /api/v1/responses باستخدام flows الخاصة به. فهذا سلوك متوقع. المشكلة هي أن مستخدمًا مصدقًا بصلاحيات منخفضة يمكنه جعل نقطة النهاية تنفذ flow يملكه مستخدم آخر عند توفير UUID flow الضحية. الدرس الأمني هو:```text
Object lookup by UUID is not authorization.
Every object lookup used by an authenticated API route must be scoped to the authenticated principal or followed by a strict ownership check before the object is used.
## تحليل الكود المصدر
تم تأكيد المشكلة على مستوى المصدر من خلال مقارنة Langflow `v1.9.0` و `v1.9.1`.
علامات المصدر التي تم التحقق منها المستخدمة للمراجعة كانت:
| الإصدار | Git commit |
| ------- | ---------- |
| v1.9.0 | `a47f2ad17eb662e940c550cfccb64a87dddd7e0b` |
| v1.9.1 | `dc26d19c1ed5b2779a3a759f78a747f47089c534` |