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



CVE-2026-118777

CVE-2026-118777: Prototype Pollution in Forge HTTP Client Cookie Management

Amit Schendel
Amit Schendel
Senior Security Researcher

Oct 31, 2026·10 min read·3 visits

Executive Summary (TL;DR)

Forge (node-forge) versions prior to 1.4.1 are vulnerable to prototype pollution and arbitrary prototype property deletion in the forge.http client when processing crafted Set-Cookie HTTP response headers from untrusted servers. Upgrading to version 1.4.1 resolves the issue.

CVE-2026-118777 is a prototype pollution vulnerability (CWE-1321) in the Forge JavaScript cryptography and networking library (distributed on npm as node-forge) prior to version 1.4.1. The flaw resides in the forge.http client subsystem, where incoming HTTP cookie names and paths parsed from Set-Cookie response headers are stored directly into standard JavaScript objects without key validation or property isolation. By returning crafted Set-Cookie headers containing keys such as __proto__ or constructor, a malicious HTTP server can inject arbitrary properties into Object.prototype, attach attributes to the global Object constructor, or delete built-in prototype methods to cause an application-wide denial of service.

Vulnerability Overview

Forge (distributed via npm as node-forge) is an open-source native JavaScript implementation of Transport Layer Security (TLS) and cryptographic utilities maintained by Digital Bazaar. Beyond cryptographic primitives such as X.509 certificate handling, ASN.1 parsing, and cipher suites, the library includes an optional HTTP client implementation (forge.http) and an XMLHttpRequest abstraction (forge.xhr) designed to operate over Forge TLS sockets. These networking components manage client-side HTTP state, including automated parsing and storage of HTTP cookies received from remote endpoints.

In versions prior to 1.4.1, the cookie management mechanism inside lib/http.js exhibits an Improperly Controlled Modification of Object Prototype Attributes vulnerability, classified under CWE-1321 (Prototype Pollution). When an application uses forge.http or forge.xhr to communicate with a remote server, the client parses incoming Set-Cookie HTTP response headers and stores the resulting cookie objects inside a two-level dictionary structure indexed by cookie name and cookie path. Because this dictionary is initialized as a standard JavaScript object literal ({}), it inherits properties and methods from Object.prototype.

The vulnerability is triggered when a remote HTTP server returns crafted Set-Cookie headers containing special property identifiers such as __proto__ or constructor. Because the cookie storage methods verify key existence using the JavaScript in operator rather than checking strictly for own properties, references to inherited prototype attributes evaluate to true. Subsequent write or delete operations against the cookie store traverse the prototype chain and directly mutate Object.prototype or the global Object constructor.

> [!NOTE] > Default Node.js imports via require('node-forge') do not load the vulnerable forge.http subsystem automatically. The exposure is limited to applications that explicitly require lib/http, invoke forge.http or forge.xhr, or include the full browser bundle (forge.all).

Root Cause Analysis

The root cause of CVE-2026-118777 lies in the combination of unisolated object initialization and unsafe property existence checks within http.createClient in lib/http.js. When a new HTTP client instance is constructed, its internal cookie jar is initialized via client.cookies = {}. In JavaScript, an object created via literal notation has its internal [[Prototype]] slot linked directly to Object.prototype, exposing inherited properties such as __proto__, constructor, toString, valueOf, and toLocaleString on every key lookup.

When the HTTP client receives a response containing a Set-Cookie header, it extracts the cookie attributes into an object and passes it to client.setCookie(cookie). To determine whether a namespace for cookie.name already exists in the cookie jar, the vulnerable implementation executes if(!(cookie.name in client.cookies)). The in operator inspects both the target object's own properties and every object along its prototype chain. If cookie.name matches any property defined on Object.prototype, the in operator returns true, and the initialization assignment client.cookies[cookie.name] = {} is bypassed.

Following this check, the function executes the nested assignment client.cookies[cookie.name][cookie.path] = cookie. When cookie.name is set to "__proto__", the first bracket access client.cookies["__proto__"] resolves via the getter on Object.prototype to Object.prototype itself. The second bracket assignment [cookie.path] = cookie then writes the attacker-controlled cookie object directly onto Object.prototype under the key specified by the cookie's path attribute. Similarly, if cookie.name is "constructor", client.cookies["constructor"] resolves to Object.prototype.constructor (the global Object constructor function), attaching the property specified by cookie.path directly onto Object.

The exact same prototype traversal flaw exists in client.getCookie(name, path) and client.removeCookie(name, path). When a server sends a Set-Cookie header with an empty value (which instructs the client to expire and remove the cookie), removeCookie executes delete client.cookies[name][path] after validating name in client.cookies and path in paths. By supplying name as "__proto__" and path as a built-in method name such as "toLocaleString", the delete operator removes the method directly from Object.prototype.

Code Analysis

Prior to version 1.4.1, the cookie management functions setCookie, getCookie, and removeCookie inside lib/http.js relied exclusively on the in operator to guard dictionary accesses. The vulnerable implementation is shown below:

// Vulnerable code in lib/http.js prior to commit 797c3f816a22748a96fceebb34eb3a6716853991
client.setCookie = function(cookie) {
  // ... validation omitted ...
  // BUG: 'in' operator checks Object.prototype chain
  if(!(cookie.name in client.cookies)) {
    client.cookies[cookie.name] = {};
  }
  // BUG: Resolves to Object.prototype[cookie.path] = cookie when cookie.name is '__proto__'
  client.cookies[cookie.name][cookie.path] = cookie;
  // ...
};
 
client.getCookie = function(name, path) {
  var rval = null;
  if(name in client.cookies) {
    var paths = client.cookies[name];
    if(path) {
      if(path in paths) {
        rval = paths[path];
      }
    }
    // ...
  }
  return rval;
};
 
client.removeCookie = function(name, path) {
  var rval = false;
  if(name in client.cookies) {
    if(path) {
      var paths = client.cookies[name];
      // BUG: Evaluates to true for built-in methods on Object.prototype
      if(path in paths) {
        rval = true;
        // BUG: Deletes built-in methods off Object.prototype
        delete client.cookies[name][path];
      }
    }
  }
  return rval;
};

In commit 797c3f816a22748a96fceebb34eb3a6716853991, the maintainers addressed the issue through two distinct defensive layers in lib/http.js. First, a helper function _hasOwn was introduced to perform safe own-property checks via Object.prototype.hasOwnProperty.call(obj, key). Calling hasOwnProperty directly off Object.prototype via .call() ensures that the check cannot be bypassed even if an object defines its own shadowing hasOwnProperty attribute.

Second, client.setCookie was updated to explicitly reject any cookie where cookie.name or cookie.path equals '__proto__'. Why are both checks necessary? If cookie.name is 'constructor', _hasOwn(client.cookies, 'constructor') returns false, causing client.cookies['constructor'] = {} to create an own property that safely shadows Object.prototype.constructor. However, in JavaScript environments, assigning obj['__proto__'] = {} on a standard object literal invokes the Object.prototype.__proto__ setter and mutates the object's prototype link rather than defining an own property named '__proto__'. Therefore, explicitly rejecting '__proto__' while using _hasOwn for all other keys prevents both prototype reassignment and inherited property traversal.

// Patched implementation in lib/http.js (commit 797c3f816a22748a96fceebb34eb3a6716853991)
var _hasOwn = function(obj, key) {
  return Object.prototype.hasOwnProperty.call(obj, key);
};
 
// Inside http.createClient:
        // FIX 1: Explicit blocklist for '__proto__' key and path
        if(cookie.name === '__proto__' || cookie.path === '__proto__') {
          return false;
        }
 
        // FIX 2: Check only own properties on client.cookies
        if(!_hasOwn(client.cookies, cookie.name)) {
          client.cookies[cookie.name] = {};
        }
        client.cookies[cookie.name][cookie.path] = cookie;
 
  client.getCookie = function(name, path) {
    var rval = null;
    // FIX 3: Restrict lookups in getCookie to own properties
    if(_hasOwn(client.cookies, name)) {
      var paths = client.cookies[name];
      if(path) {
        if(_hasOwn(paths, path)) {
          rval = paths[path];
        }
      } else {
        // ...
      }
    }
    return rval;
  };
 
  client.removeCookie = function(name, path) {
    var rval = false;
    // FIX 4: Restrict deletion in removeCookie to own properties
    if(_hasOwn(client.cookies, name)) {
      if(path) {
        var paths = client.cookies[name];
        if(_hasOwn(paths, path)) {
          rval = true;
          delete client.cookies[name][path];
          // ...
        }
      }
    }
    return rval;
  };

An assessment of the patch confirms that the fix is complete for this code path. By guarding setCookie against '__proto__' on both dimensions (name and path) and enforcing _hasOwn checks across setCookie, getCookie, and removeCookie, cookie attributes can no longer resolve to inherited properties on Object.prototype or Object.

Exploitation

Exploiting CVE-2026-118777 requires an application using forge.http or forge.xhr to process an HTTP response from an attacker-controlled server or over an unencrypted HTTP connection subject to Man-in-the-Middle (MitM) interception. No authentication or client-side user interaction is required once the client initiates the HTTP request and reads the response headers.

The repository's security regression test (tests/security/ghsa-6wvx-3r32-xmcg.js) demonstrates three distinct exploitation primitives via crafted Set-Cookie headers:

  1. Polluting Object.prototype: The server responds with a cookie named __proto__, a non-empty value, and a path parameter corresponding to the target property name:

    HTTP/1.1 200 OK
    Set-Cookie: __proto__=evil; path=polluted
     

    When the vulnerable client processes this header, Object.prototype.polluted is assigned the parsed cookie structure { name: '__proto__', value: 'evil', path: 'polluted', ... }. Consequently, any object {} in the JavaScript runtime that checks obj.polluted will evaluate to a truthy object reference.

  2. Polluting the Object Constructor: The server sets the cookie name to constructor:

    HTTP/1.1 200 OK
    Set-Cookie: constructor=evil; path=polluted
     

    Because client.cookies['constructor'] resolves to the global Object function, the assignment attaches polluted directly onto Object (Object.polluted).

  3. Deleting Object.prototype Methods (Denial of Service): The server returns an empty cookie value for __proto__ (or sets an expired timestamp) along with a path matching an existing prototype method:

    HTTP/1.1 200 OK
    Set-Cookie: __proto__=; path=toLocaleString
     

    When forge.http parses an empty or expired cookie from a response, it invokes client.removeCookie('__proto__', 'toLocaleString'). In vulnerable versions, this executes delete Object.prototype.toLocaleString (or delete Object.prototype.toString). Subsequent code anywhere in the Node.js process or browser tab that implicitly or explicitly calls .toLocaleString() or .toString() on an object will throw an unhandled TypeError: obj.toLocaleString is not a function, crashing the process or terminating script execution.

Impact Assessment

CVE-2026-118777 is rated Medium severity with a CVSS v3.1 base score of 4.8 (CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:L). The Attack Complexity is rated High (AC:H) because the vulnerable component is an outbound HTTP client rather than a listening server; successful exploitation requires the client application to connect to a malicious endpoint or traverse an untrusted network link where HTTP headers can be injected.

From an availability perspective (A:L), the most direct impact is reliable application-wide denial of service. By deleting foundational methods such as toString, valueOf, or toLocaleString from Object.prototype, a malicious server can cause immediate runtime exceptions in unrelated application logic, logging frameworks, or serialization routines sharing the same V8 isolate or browser execution context.

From an integrity perspective (I:L), the injected property value is constrained to a Forge cookie object structure rather than an arbitrary primitive string or number. However, because a JavaScript object always evaluates to true in boolean contexts, any downstream code or third-party dependency that performs unguarded truthiness checks on configuration options (e.g., if (options.polluted)) can have its control flow altered. According to FIRST EPSS metrics, the vulnerability currently carries a low exploitation probability score of 0.00255 (17.16th percentile) and is not listed in the CISA Known Exploited Vulnerabilities (KEV) catalog.

Remediation

To remediate CVE-2026-118777, upgrade node-forge (or forge) to version 1.4.1 or later, which includes commit 797c3f816a22748a96fceebb34eb3a6716853991. Update the dependency specification in package.json and reinstall packages:

npm install node-forge@^1.4.1
# or via Yarn
yarn add node-forge@^1.4.1

If an immediate dependency upgrade cannot be deployed, development teams should verify whether the vulnerable submodule is actually loaded by their application:

  • Audit Module Imports: Applications that only import default cryptographic routines via require('node-forge') in Node.js do not load lib/http.js by default and are not affected, provided forge.http and forge.xhr are never referenced.
  • Avoid Monolithic Browser Bundles: Browser applications using forge.all.js or forge.all.min.js bundle the HTTP/XHR client automatically. Switching to modular imports (such as requiring node-forge/lib/forge and only the needed cryptographic primitives like node-forge/lib/pki or node-forge/lib/aes) eliminates the vulnerable code path.
  • Freeze Built-in Prototypes: In environments where forge.http must be used prior to patching, invoking Object.freeze(Object.prototype) and Object.freeze(Object) at application startup prevents prototype mutation and property deletion.
  • Network-Layer Filtering: Where outbound requests from forge.http traverse an egress proxy or API gateway, inspect incoming Set-Cookie response headers and strip headers containing __proto__ or constructor prior to client delivery.

Official Patches

Digital BazaarGitHub Security Advisory GHSA-6wvx-3r32-xmcg
Digital BazaarPatch commit in digitalbazaar/forge
Digital BazaarForge v1.4.1 Release Notes

Fix Analysis (1)

Technical Appendix

CVSS Score
4.8/ 10
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:L
EPSS Probability
0.26%
Top 83% most exploited

Affected Systems

node-forge (npm package)forge JavaScript library (forge.http, forge.xhr, and forge.all browser bundle)

Affected Versions Detail

Product
Affected Versions
Fixed Version
node-forge
Digital Bazaar
< 1.4.11.4.1
AttributeDetail
Vulnerability TypePrototype Pollution (CWE-1321)
Affected Componentforge.http / lib/http.js (node-forge < 1.4.1)
Attack VectorNetwork (Malicious HTTP Set-Cookie Response Header)
CVSS v3.1 Score4.8 Medium (CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:L)
EPSS Score0.26% (17.16th Percentile)
ImpactObject.prototype Mutation & Denial of Service via Method Deletion
Exploit StatusPoC (Regression Tests in Repository)
CISA KEV StatusNot Listed

MITRE ATT&CK Mapping

T1059Command and Scripting Interpreter
Execution
CWE-1321
Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')

The application initializes or modifies object prototype properties through an application boundary without sufficient validation, allowing external input to mutate standard prototype attributes across the JavaScript runtime environment.

Known Exploits & Detection

GitHubOfficial security regression test suite (tests/security/ghsa-6wvx-3r32-xmcg.js) demonstrating prototype pollution and property deletion via Set-Cookie headers.

Vulnerability Timeline

Security fix committed to digitalbazaar/forge repository (797c3f816a22748a96fceebb34eb3a6716853991)
2026-10-27
GitHub Security Advisory GHSA-6wvx-3r32-xmcg and CVE-2026-118777 published
2026-10-29
Forge v1.4.1 released containing the patch
2026-10-29
CVE-2026-118777 record updated in NVD and CVE List V5 repository
2026-10-30

References & Sources

  • [1]GitHub Security Advisory: GHSA-6wvx-3r32-xmcg
  • [2]Fix Commit 797c3f816a22748a96fceebb34eb3a6716853991 in digitalbazaar/forge
  • [3]Forge Release v1.4.1
  • [4]Official CVE Record: CVE-2026-118777
  • [5]NVD Vulnerability Detail: CVE-2026-118777
  • [6]CVE List V5 JSON Record: CVE-2026-118777
  • [7]Wiz Vulnerability Database: CVE-2026-118777

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

•about 2 hours ago•CVE-2026-118775
3.7

CVE-2026-118775: ASN.1 OID First Arc Truncation and Ambiguity in node-forge

CVE-2026-118775 (GHSA-4642-5mcj-2rqw) is an integer overflow and validation flaw in the ASN.1 serialization module of Forge (node-forge) prior to version 1.4.1. The asn1.oidToDer() function fails to validate the range of the first two arcs of an Object Identifier (OID) and truncates the packed initial subidentifier to a single 8-bit integer. Applications that perform policy checks on untrusted OID strings before encoding them into Distinguished Encoding Rules (DER) format can be tricked into emitting DER bytes that correspond to a completely different, restricted OID.

Amit Schendel
Amit Schendel
5 views•10 min read
•about 3 hours ago•CVE-2026-119194
7.5

CVE-2026-119194: Algorithmic Complexity Denial of Service in pyasn1 Schemaless ASN.1 Decoder

CVE-2026-119194 is an algorithmic complexity vulnerability (CWE-407) in the pyasn1 library for Python, affecting versions 0.3.3 through 0.6.4. The flaw resides in the schemaless decoding routine ConstructedPayloadDecoderBase._decodeComponentsSchemaless used across BER, CER, and DER codecs. By sending an ASN.1 container populated with child components whose tag identifiers are separated by multiples of CPython's integer hash modulus (sys.hash_info.modulus), an unauthenticated attacker can force worst-case hash collisions in an unbounded Python set, degrading decoding performance from O(N) to O(N^2) and causing a Denial of Service (DoS).

Alon Barad
Alon Barad
5 views•9 min read
•about 4 hours ago•CVE-2026-119195
7.5

CVE-2026-119195: Quadratic-Time Denial of Service in pyasn1 BER/CER/DER Decoders

CVE-2026-119195 is an algorithmic complexity vulnerability (CWE-407) in the pyasn1 library for Python, affecting all versions prior to 0.6.5. When decoding constructed strings or indefinite-length ANY types across BER, CER, and certain DER code paths, the payload decoders repeatedly concatenate incoming fragments onto an immutable bytes object using the += operator. Because Python bytes objects cannot be resized in-place, each fragment iteration allocates a new buffer and copies all previously accumulated bytes, resulting in quadratic O(N^2) time and memory copy complexity. An unauthenticated remote attacker can supply a highly fragmented ASN.1 stream to exhaust CPU cycles and stall application worker threads.

Amit Schendel
Amit Schendel
6 views•10 min read
•about 5 hours ago•CVE-2026-119197
7.5

CVE-2026-119197: Quadratic Algorithmic Complexity Denial of Service in pyasn1 REAL Mantissa Decoder

An algorithmic complexity vulnerability (CWE-407) in pyasn1 versions prior to 0.6.5 allows unauthenticated attackers to cause a Denial of Service (DoS) via crafted ASN.1 payloads. The flaw resides in the binary-encoded ASN.1 REAL mantissa deserialization routine within RealPayloadDecoder.valueDecoder. By performing iterative byte-string slicing and repeated bitwise shifts on a growing arbitrary-precision integer, the decoder exhibits quadratic time and memory allocation complexity relative to the mantissa length. Supplying a BER-, CER-, or DER-encoded payload with a large REAL mantissa causes excessive CPU consumption and blocks application worker processes.

Amit Schendel
Amit Schendel
6 views•10 min read
•about 6 hours ago•CVE-2026-119196
7.5

CVE-2026-119196: Quadratic CPU Consumption in pyasn1 Constructed BIT STRING Decoding

A vulnerability classified under CWE-407 (Inefficient Algorithmic Complexity) exists in the pyasn1 library prior to version 0.6.5. When parsing constructed ASN.1 BIT STRING payloads under BER, CER, or schema-driven DER encoding rules, the BitStringPayloadDecoder repeatedly shifts and copies the entire accumulated bit value for each incoming fragment. Processing inputs with a large number of small constructed fragments induces quadratic CPU consumption, allowing unauthenticated remote attackers to cause a denial of service via resource exhaustion during the initial decoding phase.

Alon Barad
Alon Barad
6 views•10 min read
•about 7 hours ago•CVE-2026-119209
5.5

CVE-2026-119209: Uncontrolled Resource Consumption in pypdf XRef Stream Parser

CVE-2026-119209 is an uncontrolled resource consumption vulnerability in the pypdf Python library prior to version 6.21.3. The flaw exists within the PDF 1.5 cross-reference (XRef) stream parsing routines in pypdf/_reader.py. Due to the absence of a document-wide entry limit across chained cross-reference streams and improper validation of negative entry counts in the /Index array, an attacker can craft a compact PDF file that triggers excessive memory allocation, resulting in a Denial of Service (DoS) via MemoryError or process termination.

Alon Barad
Alon Barad
6 views•11 min read