CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-2CJR-5V3H-V2W4
5.3

GHSA-2CJR-5V3H-V2W4: Prototype Pollution via Insecure Object.assign in Evolver Mailbox Store

Alon Barad
Alon Barad
Software Engineer

Apr 23, 2026·6 min read·2 visits

PoC Available

Executive Summary (TL;DR)

Insecure use of Object.assign() in Evolver's mailbox store allows prototype pollution, enabling attackers with local file write access to manipulate application state and bypass authorization checks.

The @evomap/evolver npm package contains a prototype pollution vulnerability in its mailbox persistence logic. Versions prior to 1.69.3 use Object.assign() insecurely when parsing user-controlled updates from local persistence files. Attackers with write access to the persistence store can inject malicious prototype properties, leading to application-wide state manipulation, authorization bypass, or denial of service.

Vulnerability Overview

The @evomap/evolver package is susceptible to a Prototype Pollution vulnerability (CWE-1321) within its mailbox storage component. The issue resides in the data persistence mechanism, which parses external files to maintain state across application reboots. The vulnerability is triggered when the application processes structured data updates without adequately filtering reserved JavaScript property keys.

The attack surface requires the threat actor to have write access to the local persistence files, specifically messages.jsonl. When the application initializes or reloads its mailbox store, it ingests these files and applies the updates to memory. Because the ingestion routine does not implement input validation for object keys, malicious payloads can traverse the application boundary.

This flaw affects all versions of @evomap/evolver prior to 1.69.3. The root cause is a fundamental design flaw in how the JavaScript runtime handles prototype inheritance when combined with native object merging functions. Successful exploitation allows an attacker to alter the base Object.prototype, which subsequently impacts all objects across the active Node.js process.

Root Cause Analysis

The vulnerability originates in src/proxy/mailbox/store.js during the execution of the _applyUpdate(row) and _updateRecord(id, fields) functions. Both functions implement state merging by passing user-supplied objects directly into the Object.assign() native method. The Object.assign() method copies all enumerable own properties from one or more source objects to a target object, but it does not inherently filter dangerous keys like __proto__, constructor, or prototype.

In JavaScript, the __proto__ property acts as an accessor to an object's internal [[Prototype]]. When a JSON parser processes a payload containing the __proto__ key, the resulting object retains this structure. If this object is subsequently passed as a source to Object.assign() where the target is a standard object, the JavaScript engine assigns the properties nested under __proto__ to the target object's prototype, which is typically the global Object.prototype.

The data flow begins when the mailbox store invokes its load() method to parse messages.jsonl. Each line is deserialized and passed to _applyUpdate(). If an attacker constructs a payload where the row.fields object contains a __proto__ property, the assignment operation merges the nested properties into the prototype of the existing object. As the existing object inherits from Object.prototype, the target of the assignment effectively becomes the global prototype chain.

Code Analysis

The vulnerable code path is straightforward and relies on native JavaScript functions without intermediate sanitization. In the affected versions, the _applyUpdate method directly merges the fields object extracted from the deserialized row into the existing record object stored in the internal _index.

// Vulnerable function in src/proxy/mailbox/store.js
_applyUpdate(row) {
  if (row._op === 'update') {
    const existing = this._index[row.id];
    // VULNERABLE: Direct Object.assign without key filtering
    if (existing) Object.assign(existing, row.fields);
    else this._index[row.id] = row.fields;
  }
}

The issue is identically replicated in the _updateRecord function, which handles in-memory updates. Because row.fields is derived entirely from the untrusted persistence file, an attacker can specify any arbitrary object graph. When Object.assign encounters the __proto__ key within row.fields, it iterates over the properties defined within that __proto__ block and assigns them to the prototype of existing.

// Patched logic requires explicit key filtering
function safeAssign(target, source) {
    for (let key in source) {
        if (key === '__proto__' || key === 'constructor' || key === 'prototype') continue;
        if (Object.prototype.hasOwnProperty.call(source, key)) {
            target[key] = source[key];
        }
    }
    return target;
}

The remediation requires replacing Object.assign with a secure assignment utility, such as the safeAssign function shown above. This patched logic iterates over the source object keys and explicitly rejects __proto__, constructor, and prototype. It also ensures that only direct properties of the source object are copied, mitigating prototype pollution vectors.

Exploitation

Exploitation of this vulnerability requires the attacker to append a valid JSON Lines (JSONL) entry to the messages.jsonl file. This necessitates local filesystem access or an adjacent vulnerability, such as a localized file write flaw, that allows appending data to the storage directory utilized by @evomap/evolver.

The attacker constructs a serialized JSON object that defines the _op property as update and specifies a valid target id to ensure the logic enters the vulnerable Object.assign branch. The fields object is constructed with a __proto__ key containing the properties the attacker wishes to inject into the global application state.

{
  "_op": "update",
  "id": "msg-001",
  "fields": {
    "__proto__": {
      "polluted": true,
      "isAdmin": true
    },
    "text": "Malicious update applied"
  }
}

Upon application startup or when the mailbox service triggers a reload, the store parses this line. The application resolves this._index["msg-001"] and invokes Object.assign. The JavaScript engine processes the __proto__ key, assigning polluted: true and isAdmin: true to the global Object.prototype. Subsequently, any newly created or existing object in the runtime environment that lacks its own isAdmin property will inherit the value true.

Impact Assessment

The vulnerability carries a CVSS v3.1 base score of 5.3 (CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:U/C:L/I:L/A:H). The attack vector is defined as Local (AV:L), and it requires High privileges (PR:H) because the threat actor must be able to modify the application's underlying persistence files. The complexity is High (AC:H) as exploitation depends on the specific authorization and operational logic implemented by the consuming application.

The primary consequence is logic manipulation and authorization bypass. If the application or any of its dependencies relies on property checks to determine access rights (e.g., if (user.isAdmin)), the polluted prototype will evaluate to true regardless of the user's actual permissions. This effectively grants administrative access to unprivileged users across the entire application instance.

Furthermore, the vulnerability introduces a significant Denial of Service (DoS) risk. An attacker can pollute native object functions such as toString, valueOf, or hasOwnProperty by overwriting them with primitive values or incompatible types. When the application attempts to invoke these functions, the runtime will throw a TypeError, causing the Node.js process to crash.

Remediation

The official mitigation is to upgrade the @evomap/evolver package to version 1.69.3. This release replaces the native Object.assign() calls in the persistence logic with a secure merging function that filters prototype-related keys. Software engineers must verify the installed package version in their package-lock.json or yarn.lock files to ensure the patch is applied.

For environments where immediate upgrading is not feasible, administrators must restrict filesystem permissions. Ensure that the messages.jsonl file and its parent directory are owned by the specific application user account. Revoke write permissions for all other users to prevent unauthorized modification of the persistence store.

As a defense-in-depth measure, Node.js applications can be hardened against prototype pollution globally by utilizing runtime flags. Starting the application with node --disable-proto=throw or node --disable-proto=delete instructs the V8 engine to either throw an exception or delete the __proto__ key upon instantiation. This neutralizes the specific vector used in this vulnerability.

Official Patches

EvoMapEvolver GitHub Repository

Technical Appendix

CVSS Score
5.3/ 10
CVSS:3.1/AV:L/AC:H/PR:H/UI:N/S:U/C:L/I:L/A:H

Affected Systems

@evomap/evolver npm packageNode.js applications utilizing Evolver for mailbox management

Affected Versions Detail

Product
Affected Versions
Fixed Version
@evomap/evolver
EvoMap
< 1.69.31.69.3
AttributeDetail
Vulnerability TypePrototype Pollution
CWE IDCWE-1321
Attack VectorLocal (File Modification)
CVSS Base Score5.3
ImpactAuthorization Bypass, DoS, Logic Manipulation
Exploit StatusProof of Concept Available

MITRE ATT&CK Mapping

T1574.011Hijack Execution Flow: Prototype Pollution
Privilege Escalation
T1059Command and Scripting Interpreter
Execution
CWE-1321
Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')

The product receives input from an upstream component, but it does not restrict or incorrectly restricts the attributes that can be modified when the input is used to update the prototype of an object.

Known Exploits & Detection

Research ContextProof of concept payload targeting the messages.jsonl file format.

Vulnerability Timeline

Vulnerability Discovered by xeloxa
2026-04-01
Advisory Published
2026-04-22

References & Sources

  • [1]GitHub Advisory: GHSA-2cjr-5v3h-v2w4
  • [2]OSV Record: GHSA-2cjr-5v3h-v2w4
  • [3]EvoMap Evolver Repository

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.