| Advisory ID | github_osv/GHSA-7j65-65cr-6644 |
| Aliases |
CVE-2026-46478
|
| Summary | FlowiseAI: DatasetRow create+update mass-assignment allows cross-workspace row takeover ## Summary **Type:** Mass assignment via `Object.assign(entity, body)` -> client-controlled `workspaceId` (and on create, `id`) overwritten on the DatasetRow entity -> cross-workspace data takeover and IDOR. **File:** `packages/server/src/services/dataset/index.ts` **Root cause:** The DatasetRow controller/service constructs a `new DatasetRow()` 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 datasetrow entity's sibling controllers and as `DocumentStore` before it was patched in commit 840d2ae. ## Affected Code **File:** `packages/server/src/services/dataset/index.ts` ```ts // create (line 274) and update (line 315) Object.assign(newRow, rowBody) // <-- BUG: rowBody.id, rowBody.datasetId 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 datasetrow 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/datasetrows/<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 datasetrow 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 datasetrow 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). DatasetRows hold individual training/evaluation records. The mass assignment lets a member rebind a row to a Dataset in another workspace via `datasetId`, exposing the row content to the destination workspace. **Preconditions:** Authenticated session with edit permission for the source datasetrow. 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/6051 (allowlist pattern applied). ```ts // Allowlist pattern (matches commit 840d2ae for DocumentStore): const updatedDatasetRow = new DatasetRow() if (body.<allowed_field_1> !== undefined) updatedDatasetRow.<allowed_field_1> = body.<allowed_field_1> if (body.<allowed_field_2> !== undefined) updatedDatasetRow.<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. |
| Status | Published |
| Exploitability | 0.5 |
| Weighted Severity | 7.9 |
| Risk | 4.0 |
| Affected and Fixed Packages | Package Details |
| Introduced and Fixed Package Commit Patches | Package Commit Patches Details |
| System | Score | Found at |
|---|---|---|
| cvssv3.1 | 8.8 | https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/05/GHSA-7j65-65cr-6644/GHSA-7j65-65cr-6644.json |
| cvssv4 | 7.7 | https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/05/GHSA-7j65-65cr-6644/GHSA-7j65-65cr-6644.json |
| generic_textual | HIGH |
No EPSS data available for this advisory.
| Patch URL | |
|---|---|
| There are no known patches. | |
| Attack Vector (AV) | Attack Complexity (AC) | Privileges Required (PR) | User Interaction (UI) | Scope (S) | Confidentiality Impact (C) | Integrity Impact (I) | Availability Impact (A) |
|---|---|---|---|---|---|---|---|
network adjacent_network local physical |
low high |
none low high |
none required |
unchanged changed |
high low none |
high low none |
high low none |
| Attack Vector (AV) | Attack Complexity (AC) | Attack Requirements (AT) | Privileges Required (PR) | User Interaction (UI) | Vulnerable System Impact Confidentiality (VC) | Vulnerable System Impact Integrity (VI) | Vulnerable System Impact Availability (VA) | Subsequent System Impact Confidentiality (SC) | Subsequent System Impact Integrity (SI) | Subsequent System Impact Availability (SA) |
|---|---|---|---|---|---|---|---|---|---|---|
network adjacent local physical |
low high |
none present |
none low high |
none passive active |
high low none |
high low none |
high low none |
high low none |
high low none |
high low none |
Vector: SSVCv2/E:N/A:Y/T:T/P:M/B:A/M:M/D:T/2026-06-09T15:33:04Z/
Decision: Track
Source URL: https://github.com/cisagov/vulnrichment/blob/develop/2026/46xxx/CVE-2026-46478.json
Source Advisory: vulnrichment/CVE-2026-46478
[{'Exploitation': 'none'},
{'Automatable': 'yes'},
{'Technical Impact': 'total'},
{'Mission Prevalence': 'minimal'},
{'Public Well-being Impact': 'material'},
{'Mission & Well-being': 'medium'}]