GHSA-78pr-c5x5-jggc: Flowise: IDOR via mass assignment breaks tenant isolation

GHSA-78pr-c5x5-jggc HIGH
Published May 14, 2026
CISO Take

Flowise's Assistant API (versions ≤3.1.1) contains a mass assignment flaw where the server blindly copies the full request body onto the entity via Object.assign() without any field allowlist, letting any authenticated user overwrite the workspaceId field and transfer an AI assistant—along with its system prompt, tool configuration, and any embedded credentials—into an arbitrary tenant workspace. This is a full multi-tenant isolation breach: workspace UUIDs are trivially enumerable from standard API responses, meaning no privilege escalation or reconnaissance tooling is required beyond a single authenticated session. The exploit leaves no cross-workspace audit trail since the persistence layer records it as a normal assistant update, making post-incident detection difficult without direct database inspection. Upgrade to Flowise 3.1.2 immediately; the fix applies the same explicit field-by-field allowlist already deployed for the DocumentStore entity in commit 840d2ae.

Sources: GitHub Advisory ATLAS

What is the risk?

High. The vulnerability is trivially exploitable—an attacker needs only a valid session and one modified JSON field in a standard PUT request. Workspace UUIDs are exposed in routine API responses, so target selection requires no additional tooling. The attack crosses tenant boundaries silently, with no cross-workspace event generated, making detection dependent on proactive database auditing rather than log monitoring. Every Flowise deployment running ≤3.1.1 with more than one workspace and more than one user is exposed. The 76 other CVEs in the same package suggest a pattern of security debt in this codebase worth monitoring.

Attack Kill Chain

Initial Access
Attacker authenticates to Flowise using any valid workspace account—no elevated privileges or social engineering required.
AML.T0012
Reconnaissance
Attacker enumerates target workspace UUIDs from standard API responses (e.g., GET /api/v1/workspaces or workspaceId fields in any cross-referenced object).
AML.T0006
Exploitation
Attacker issues PUT /api/v1/assistants/<id> with a JSON body containing 'workspaceId': '<target-workspace-uuid>'; the unguarded Object.assign() call persists the attacker-supplied ownership field to the database.
AML.T0049
Impact
The assistant entity (system prompt, tool definitions, embedded credentials) is now owned by the target workspace; the victim tenant loses access and no cross-workspace audit event is generated.
AML.T0083

What systems are affected?

Package Ecosystem Vulnerable Range Patched
flowise npm <= 3.1.1 3.1.2

Do you use flowise? You're affected.

Severity & Risk

CVSS 3.1
N/A
EPSS
N/A
Exploitation Status
No known exploitation
Sophistication
Trivial

What should I do?

5 steps
  1. Patch immediately: Upgrade to Flowise 3.1.2—the fix applies an explicit allowlist to the Assistant create and update paths (PR #6128).

  2. Verify integrity: Query your database for assistants with unexpected workspaceId values—specifically rows where workspaceId does not match the workspace of the user who last modified them (cross-reference update timestamps with auth logs).

  3. Interim workaround if patching is delayed: Restrict PUT /api/v1/assistants/* at the WAF or reverse-proxy layer to admin roles only, or block the endpoint from non-owner principals until the patch is applied.

  4. Expand scope review: Audit other entity controllers in your Flowise version for the same Object.assign(entity, body) pattern—the advisory explicitly notes this affected sibling controllers and DocumentStore before commit 840d2ae.

  5. Detection: Alert on assistant workspaceId field changes where the new workspaceId differs from the authenticated user's workspace context.

Classification

Compliance Impact

This CVE is relevant to:

EU AI Act
Art. 9 - Risk management system
ISO 42001
A.6.2.6 - Access control for AI systems
NIST AI RMF
MEASURE-2.7 - AI system security and resilience are evaluated and documented
OWASP LLM Top 10
LLM06 - Excessive Agency

Frequently Asked Questions

What is GHSA-78pr-c5x5-jggc?

Flowise's Assistant API (versions ≤3.1.1) contains a mass assignment flaw where the server blindly copies the full request body onto the entity via Object.assign() without any field allowlist, letting any authenticated user overwrite the workspaceId field and transfer an AI assistant—along with its system prompt, tool configuration, and any embedded credentials—into an arbitrary tenant workspace. This is a full multi-tenant isolation breach: workspace UUIDs are trivially enumerable from standard API responses, meaning no privilege escalation or reconnaissance tooling is required beyond a single authenticated session. The exploit leaves no cross-workspace audit trail since the persistence layer records it as a normal assistant update, making post-incident detection difficult without direct database inspection. Upgrade to Flowise 3.1.2 immediately; the fix applies the same explicit field-by-field allowlist already deployed for the DocumentStore entity in commit 840d2ae.

Is GHSA-78pr-c5x5-jggc actively exploited?

No confirmed active exploitation of GHSA-78pr-c5x5-jggc has been reported, but organizations should still patch proactively.

How to fix GHSA-78pr-c5x5-jggc?

1. Patch immediately: Upgrade to Flowise 3.1.2—the fix applies an explicit allowlist to the Assistant create and update paths (PR #6128). 2. Verify integrity: Query your database for assistants with unexpected workspaceId values—specifically rows where workspaceId does not match the workspace of the user who last modified them (cross-reference update timestamps with auth logs). 3. Interim workaround if patching is delayed: Restrict PUT /api/v1/assistants/* at the WAF or reverse-proxy layer to admin roles only, or block the endpoint from non-owner principals until the patch is applied. 4. Expand scope review: Audit other entity controllers in your Flowise version for the same Object.assign(entity, body) pattern—the advisory explicitly notes this affected sibling controllers and DocumentStore before commit 840d2ae. 5. Detection: Alert on assistant workspaceId field changes where the new workspaceId differs from the authenticated user's workspace context.

What systems are affected by GHSA-78pr-c5x5-jggc?

This vulnerability affects the following AI/ML architecture patterns: agent frameworks, multi-tenant AI platforms, LLM agent deployments, no-code AI workflow builders.

What is the CVSS score for GHSA-78pr-c5x5-jggc?

No CVSS score has been assigned yet.

Technical Details

NVD Description

## Summary **Type:** Mass assignment via `Object.assign(entity, body)` -> client-controlled `workspaceId` (and on create, `id`) overwritten on the Assistant entity -> cross-workspace data takeover and IDOR. **File:** `packages/server/src/services/assistants/index.ts` **Root cause:** The Assistant controller/service constructs a `new Assistant()` and copies the request body into it via `Object.assign(...)` without an explicit field allowlist. The request body therefore can include `workspaceId`, `id`, `createdDate`, `updatedDate`. The server only rebinds *some* of these after the assign (e.g. on create, it overwrites `workspaceId` but not `id`; on update, it overwrites `id` but not `workspaceId`). The remaining client-controlled values land directly on the persisted row, breaking workspace isolation. Same root pattern as the assistant entity's sibling controllers and as `DocumentStore` before it was patched in commit 840d2ae. ## Affected Code **File:** `packages/server/src/services/assistants/index.ts` ```ts // create (line 303) and update (line 381) Object.assign(newAssistant, requestBody) // <-- BUG: requestBody.id, requestBody.workspaceId accepted ``` **Why it's wrong:** `Object.assign(target, source)` copies every own enumerable property of `source` onto `target`. The TypeORM/SQL persistence layer below it does not strip ownership-bearing columns, so `workspaceId` set in the request body lands as the new `workspaceId` of the persisted row. The DocumentStore patch (commit 840d2ae) demonstrated the intended fix shape (explicit field-by-field allowlist) but it has not been applied to this entity. ## Exploit Chain 1. Attacker is an authenticated member of workspace A. They have a session cookie / JWT for the Flowise web UI. State at this point: attacker can read and write entities scoped to workspace A. 2. Attacker creates a assistant in workspace A via the documented API (or reuses an existing one they own). They note its entity `id`. 3. Attacker issues a `PUT /api/v1/assistants/<id>` (or equivalent endpoint) with a JSON body that includes `"workspaceId": "<workspace-B-id>"` (an arbitrary other workspace's UUID). State at this point: the request reaches the controller as a workspace-A authenticated request. 4. The controller calls `Object.assign(updateEntity, body)`. The body's `workspaceId` overwrites the entity's `workspaceId` field. The persistence layer commits the row. 5. Final state: the assistant row is now owned by workspace B. Workspace B members can see it, modify it, and use it. Workspace A loses access (it no longer satisfies their workspace filter). The original creator's workspace audit shows nothing because the operation looked like a normal update. ## Security Impact **Severity:** High. Cross-workspace boundary violation by any authenticated workspace member. **Attacker capability:** Any authenticated user with permission to update a assistant can move it to any workspace whose UUID they can guess or enumerate (workspace UUIDs are exposed in many API responses, so enumeration is trivial). Assistants encapsulate LLM configuration, instructions, attached tools, and credentials. Cross-workspace movement via `workspaceId` overwrite exposes the assistant (including its system prompt and tool list) to the destination workspace. **Preconditions:** Authenticated session with edit permission for the source assistant. No second factor required. Workspace UUIDs are exposed via the `/api/v1/workspaces` listing or via any cross-referenced object's `workspaceId` field, so target enumeration is trivial. **Differential:** PoC-verified by source inspection of the original GHSA-q4pr-4r26-c69r. Patched build (with the suggested fix below) refuses the `workspaceId` field; vulnerable build accepts it and persists it. ## Suggested Fix Already fixed in PR https://github.com/FlowiseAI/Flowise/pull/6128 (allowlist pattern applied). ```ts // Allowlist pattern (matches commit 840d2ae for DocumentStore): const updatedAssistant = new Assistant() if (body.<allowed_field_1> !== undefined) updatedAssistant.<allowed_field_1> = body.<allowed_field_1> if (body.<allowed_field_2> !== undefined) updatedAssistant.<allowed_field_2> = body.<allowed_field_2> // ...whitelist only the documented fields. Never copy id, workspaceId, createdDate, updatedDate from the client. ``` Regression tests should assert that a request body containing `workspaceId`, `id`, `createdDate`, or `updatedDate` is rejected (or at minimum: does not change those columns on the persisted row) for both create and update paths.

Exploitation Scenario

An attacker with a legitimate account in workspace A (a lower-privileged tenant, e.g., a contractor environment) calls GET /api/v1/workspaces or inspects any API response containing workspaceId to enumerate the UUID of workspace B (e.g., the finance team's tenant). The attacker then issues PUT /api/v1/assistants/<assistant-id> with a JSON body that includes 'workspaceId': '<workspace-B-uuid>' alongside normal update fields. The unguarded Object.assign() in the service layer persists this field to the database. Workspace B members now have full access to the assistant—including its system prompt, configured tools, and any stored API keys—while workspace A loses visibility. The audit log in workspace A records only a normal assistant update with no indication of cross-workspace transfer, leaving the breach undetected until a workspace B member notices an unexpected asset.

Timeline

Published
May 14, 2026
Last Modified
May 14, 2026
First Seen
May 14, 2026

Related Vulnerabilities