Severity Daily

IT and AI security incidents, checked against the primary source

Tag: CVE-2026-86250

  • h3 scored its own cookie-loop hang as Moderate; the CVE published six months later says High, and the whole gap is one availability metric

    h3 scored its own cookie-loop hang as Moderate; the CVE published six months later says High, and the whole gap is one availability metric

    GitHub’s advisory database still shows “No known CVE” for the flaw CVE-2026-86250 describes, and every affected version — along with the only fix — is a pre-release build.

    What happened

    On September 6, 2026, VulnCheck published CVE-2026-86250 against h3, the HTTP server framework maintained by the h3js project and used as the request layer under Nitro and Nuxt. The NVD record went live at 2026-09-06T12:17:15.767 and describes the flaw this way:

    “h3 versions before 2.0.1-rc.18 fail to validate the chunk count parsed from user-controlled cookie values in setChunkedCookie() and deleteChunkedCookie() functions. Attackers can send a crafted cookie header with an extremely large chunk count to trigger an O(n²) cleanup loop that hangs the server process.”

    VulnCheck rates it High: 7.5 on CVSS 3.1, vector AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H, and 8.7 on CVSS 4.0. The weakness is CWE-400, uncontrolled resource consumption. Affected versions are >= 2.0.0-beta.4, < 2.0.1-rc.18; the fix is 2.0.1-rc.18.

    None of that is new. The h3 project published its own advisory for the same flaw, GHSA-q5pr-72pq-83v3, on March 21, 2026, reviewed and last updated March 23. Same functions, same version ranges, same fix, same CWE, same reporter — credited to @offset in both records.

    What differs is the score. The h3 advisory rates the flaw Moderate, at 5.3, on the vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L.

    Set the two CVSS 3.1 vectors side by side and they are identical in seven of eight metrics. Attack vector network, attack complexity low, no privileges, no user interaction, scope unchanged, no confidentiality impact, no integrity impact. The only difference is the last one: the project wrote A:L, and VulnCheck wrote A:H. That single letter is the entire 2.2-point gap, and on CVSS 4.0 it is the difference between a number that would not have been calculated at all and 8.7.

    The h3 advisory’s own text describes the impact. It states that “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.” It walks through the mechanism: the chunk count is parsed at src/utils/cookie.ts with, in the advisory’s own annotation, “no upper bound check — attacker controls this value,” and the cleanup path runs one deleteCookie per chunk, each of which “scans ALL existing set-cookie headers.” At the example value it puts the result at roughly 1012 operations. It adds that “session usage is extremely common in web applications.”

    As of retrieval, GitHub’s advisory database page for GHSA-q5pr-72pq-83v3 lists “No known CVE.” VulnCheck’s advisory for CVE-2026-86250 explicitly references the GHSA. The link runs one way.

    Why it matters

    Start with which score is right, because the advisory that carries the lower one contains the evidence against it.

    CVSS 3.1 defines A:L as reduced performance or interruptions in resource availability, with the attacker unable to completely deny service. A:H is a total loss of availability, or a sustained denial the attacker controls. A single unauthenticated request that hangs the process is the second thing. The h3 advisory says “hangs the process” in its own summary sentence. It scored its flaw against a definition its own description does not meet.

    This is worth being fair about. Self-scoring is genuinely hard, and maintainers do it more honestly than almost anyone — the alternative is a flaw nobody documents at all. The specific trap here is a common one: the availability metric reads intuitively like a question about how degraded the service gets, when the specification is asking whether the attacker can take it away entirely. A hang feels less severe than a crash. Under CVSS it is not; a hung process serving nothing is a total loss of availability, and it does not restart itself the way a crashed one under a supervisor does.

    The consequence is not academic. A 5.3 and a 7.5 land in different buckets in almost every process built on top of these records. Dependency scanners default to alerting on High and above. Vulnerability management policies set different remediation clocks at Moderate. A team that saw the h3 advisory in March, read Moderate, and put it in the backlog behind the Highs made that decision on a number that the same advisory’s prose contradicts. Nothing about the flaw changed between March and September. The published severity did.

    Then there is the six-month gap, and what it did to visibility. From March 21 to September 6, this flaw existed in exactly one place: GitHub’s advisory database, with no CVE attached. Software composition analysis tools that consume the GitHub advisory feed saw it. Tools keyed to NVD saw nothing, because there was nothing to see. Those two populations are both large, and for 169 days they had different pictures of the same dependency. Now both have a record, and the records disagree about how bad it is, and the older of the two still says no CVE exists.

    One scope limit deserves stating plainly, because it cuts against alarm and it explains part of what happened. Every affected version is a pre-release. The range starts at 2.0.0-beta.4 and ends before 2.0.1-rc.18; there is no stable h3 v2 release in it. The h3 v1 line, which is what a great many Nuxt and Nitro deployments are actually running today, is not in the affected range at all. So the real population here is teams who moved to h3 v2 early — a smaller group than “everyone downstream of Nuxt,” and one that has, on the whole, opted into some instability.

    But the fix is a pre-release too, and that is the part that bites. 2.0.1-rc.18 is the only version that closes this, and a release candidate is precisely what many organizations’ dependency policies forbid in production. The remediation and the prohibition point in opposite directions. If your policy says no pre-release dependencies and your lockfile already contains an h3 v2 beta, the policy was violated before the vulnerability existed, and the only compliant path forward is backward — to v1.

    What to do

    Check whether you have h3 v2 anywhere, directly or transitively: npm ls h3 across your workspaces, and grep lockfiles for [email protected].. Anything on the v1 line is outside the affected range and needs no action for this.

    If you find a v2 build below 2.0.1-rc.18, move to 2.0.1-rc.18 or later. That is the only fix either record names. If a pre-release dependency policy blocks that, the honest options are a documented exception or a move back to h3 v1; there is no stable v2 build that resolves this.

    For an interim control while you schedule the upgrade, the attack has a distinctive signature at the edge. The trigger is a cookie whose value matches the chunked-cookie marker followed by a chunk count — the advisory’s example is h3=__chunked__999999. A reverse proxy or WAF rule that rejects requests carrying a chunked-cookie value with an implausibly large count will stop this before it reaches the session handler. Pick the bound from your own application: real chunked cookies exist to carry a session across a handful of cookie-sized pieces, not a million.

    The broader habit worth taking from this: when a project advisory and a CVE record disagree on severity, read the advisory’s description before you trust either number. Here the description settles the question, and it was sitting in the lower-scored record the whole time.

    Sourcing note

    Checked directly: the NVD record for CVE-2026-86250 (published 2026-09-06T12:17:15.767) for the description quoted above, both CVSS vectors, the CWE, and the affected and fixed version ranges; GHSA-q5pr-72pq-83v3, retrieved twice at two different URLs — the project’s own security-advisories page and the github.com/advisories mirror — for the advisory text, the code annotations, the March 21, 2026 publication date with its March 23 review, the Moderate rating and the 5.3 vector, and the credit to @offset; and VulnCheck’s advisory page for CVE-2026-86250, which confirms the High rating, the 8.7 CVSS 4.0 score, a disclosure date of September 6, 2026, and an explicit reference back to the GHSA.

    The two GHSA retrievals agreed on every value used here. The “No known CVE” line is what the github.com/advisories mirror displayed at the time of retrieval; GitHub backfills CVE identifiers onto reviewed advisories on its own schedule, so that may resolve without anyone doing anything, and this story treats it as a lag rather than a defect.

    Unresolved: whether the h3 maintainers were consulted on the CVSS 3.1 vector VulnCheck assigned, and whether either party intends to revise. Neither record contains a rationale for its availability metric; the argument above is drawn from the CVSS 3.1 specification’s own definitions applied to the h3 advisory’s description, and it is this publication’s reading, not a statement by either party. The record carries no CISA KEV fields and no federal deadline. There is no indication of exploitation, and neither advisory claims any.