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

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·19 visits

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.

More Reports

•23 minutes ago•GHSA-8FPG-XM3F-6CX3
7.4

GHSA-8FPG-XM3F-6CX3: Authentication Fail-Open via Unvalidated Server Responses in Auth.js

In Auth.js (specifically next-auth version 5), server-side configuration errors or backend exceptions can cause existence-based authentication and authorization checks to fail open. When the underlying core engine (@auth/core) encounters a configuration error or runtime exception, it returns an HTTP 500 Internal Server Error response containing a JSON-formatted error description payload. Prior to the fix, the next-auth wrappers read this response body using response.json() without validating the HTTP status code. Because any parsed JavaScript object evaluates to truthy, common existence-based checks incorrectly evaluated to true, letting unauthenticated requests pass.

Alon Barad
Alon Barad
0 views•7 min read
•about 2 hours ago•CVE-2026-6790
5.3

CVE-2026-6790: Host/Authority Header Desynchronization in Eclipse Jetty

A host/authority desynchronization vulnerability exists in Eclipse Jetty's handling of HTTP/2 and HTTP/3 requests. When both an ':authority' pseudo-header and a standard 'Host' header are present in a request, Jetty fails to validate that they represent the same target host. This desynchronization creates a host-confusion or 'split-brain' state, enabling attackers to bypass access control lists, escape virtual host isolation, poison web caches, or manipulate redirect targets in backend applications.

Amit Schendel
Amit Schendel
4 views•5 min read
•about 3 hours ago•CVE-2026-8384
5.3

CVE-2026-8384: URI Path Parameter Parser State-Desynchronization Path Traversal in Eclipse Jetty

A path traversal vulnerability exists in Eclipse Jetty due to a state-desynchronization defect in the URI parsing state machine inside URIUtil.java. This defect allows unauthenticated remote attackers to bypass path-based security constraints enforced by downstream filters, application gateways, or authorization modules by crafting URIs with path parameter delimiters and parent directory traversal sequences.

Amit Schendel
Amit Schendel
4 views•7 min read
•about 4 hours ago•GHSA-WHVH-WF3X-G77J
0.0

GHSA-WHVH-WF3X-G77J: Improper Access Control and Listing Bypass in JupyterLab Extension Manager

An improper access control vulnerability in JupyterLab allows programmatic installation of blocked or non-allowed extensions. The vulnerability is caused by a missing await keyword when invoking the asynchronous checking method, leading Python to evaluate the returned coroutine object as truthy. Furthermore, the check lacks proper canonicalization of package names, enabling an attacker to bypass blocklists using casing or character variants.

Amit Schendel
Amit Schendel
6 views•6 min read
•about 5 hours ago•CVE-2026-42980
7.8

CVE-2026-42980: Windows Kernel Local Privilege Escalation via WMI Integer Underflow

An unsigned 32-bit integer underflow vulnerability in the Windows Management Instrumentation (WMI) serialization subsystem of ntoskrnl.exe allows local authenticated users with low privileges to corrupt adjacent kernel pool allocations, execute arbitrary kernel-mode read and write operations, and perform a Token Swap attack to escalate their privileges to NT AUTHORITY\SYSTEM.

Amit Schendel
Amit Schendel
7 views•7 min read
•about 5 hours ago•GHSA-H5V5-8746-G7MM
6.0

GHSA-H5V5-8746-G7MM: JupyterLab PluginManager Lock-Rule Enforcement Bypass

JupyterLab's PluginManager contains an authorization bypass vulnerability allowing authenticated users to modify the state of locked extensions or plugins. Although the frontend user interface visually locks and disables toggle components for administrative configurations, the backend API fails to perform robust validation. Standard users can craft direct HTTP API requests to modify plugin states, completely bypassing administrative restrictions.

Amit Schendel
Amit Schendel
8 views•5 min read