GitHub Security Advisory: GHSA-3vj8-jmxq-cgj5
Package: h3 (NPM)
Severity: HIGH (CVSS 7.4)
CWE: CWE-290: Authentication Bypass by Spoofing
Vulnerable versions: >= 2.0.0-0, < 2.0.1-rc.15
Patched in: 2.0.1-rc.15

Summary: h3 has a middleware bypass with one gadget

Details:
# H3 NodeRequestUrl bugs 

Vulnerable pieces of code : 
```js
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 

```js 
// _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  : 
```js
 this.#url = new NativeURL(this.href);
```
Where is the `this.href` comes from ? 
```js 
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 : 
```js
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 
```js
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 : 
```py
import requests
url = "http://localhost:3000