| Affected_by_vulnerabilities |
| 0 |
| url |
VCID-uj7r-xwhg-nbgh |
| vulnerability_id |
VCID-uj7r-xwhg-nbgh |
| summary |
Nitro has an Open Redirect via Protocol-Relative URL Bypass in Wildcard Route Rules
A redirect route rule like:
```ts
routeRules: {
"/legacy/**": { redirect: "/**" }
}
```
is intended to rewrite paths within the same host. Before the patch, an attacker could turn the rewrite into a cross-host redirect by sliding an extra slash in after the rule prefix. Example exploit:
```
GET /legacy//evil.com
```
Nitro stripped `/legacy` from the matched pathname and joined the remainder against the rule's target. The remainder was `//evil.com`, which the join preserved verbatim, so Nitro responded with `Location: //evil.com`. Browsers resolve `//evil.com` as a protocol-relative URL against the current scheme, sending the user to `https://evil.com`.
### Are you affected?
Users may be affected if **all** of the following are true:
1. Their project uses Nitro's `routeRules` with a `redirect` entry.
2. The target uses a `/**` wildcard suffix to forward sub-paths (e.g. `redirect: "/**"`, `redirect: "/new/**"`, `proxy: { to: "http://upstream/**" }`).
3. The `redirect` rule is _not_ handled natively at the CDN layer. The `vercel`, `netlify`, `cloudflare-pages`, and `edgeone` presets translate `routeRules.redirect` into platform config (`vercel.json`, `_redirects`, EdgeOne v3 config) and serve the redirect at the edge — those deployments bypass the Nitro runtime entirely and are not affected. Every other preset executes the redirect through the Nitro runtime and can be vulnerable.
## Impact
Open redirect from any host serving Nitro with a wildcard `redirect` rule. The redirect target is fully attacker-controlled, the URL looks legitimate (it starts with the victim's domain), and the browser silently follows it.
## Patched versions
Upgrade to one of:
- [2.13.4](https://github.com/nitrojs/nitro/releases/tag/v2.13.4) or later (or upgrade lockfile with latest ufo 1.6.4+)
- [3.0.260429-beta](https://github.com/nitrojs/nitro/releases/tag/v3.0.260429-beta) or later (https://github.com/nitrojs/nitro/pull/4236)
The fix has two parts:
1. `ufo` is bumped to `^1.6.4` ([unjs/ufo@5cd9e67](https://github.com/unjs/ufo/commit/5cd9e676711af3f4e4b5398ddf6ca8d52c1c7e1f)), which collapses any run of leading slashes to a single `/` inside `withoutBase`. This covers the typical `"/scope/**"` rule.
2. The Nitro runtime additionally collapses leading `//` before joining when the rule path itself is `/**` (in rare case which case `withoutBase` is never called and the raw pathname flows straight into `joinURL("", …)`). |
| references |
| 0 |
| reference_url |
https://api.first.org/data/v1/epss?cve=CVE-2026-44372 |
| reference_id |
|
| reference_type |
|
| scores |
| 0 |
| value |
0.0003 |
| scoring_system |
epss |
| scoring_elements |
0.09083 |
| published_at |
2026-06-05T12:55:00Z |
|
| 1 |
| value |
0.0003 |
| scoring_system |
epss |
| scoring_elements |
0.09048 |
| published_at |
2026-06-09T12:55:00Z |
|
| 2 |
| value |
0.0003 |
| scoring_system |
epss |
| scoring_elements |
0.09021 |
| published_at |
2026-06-08T12:55:00Z |
|
| 3 |
| value |
0.0003 |
| scoring_system |
epss |
| scoring_elements |
0.09079 |
| published_at |
2026-06-07T12:55:00Z |
|
| 4 |
| value |
0.0003 |
| scoring_system |
epss |
| scoring_elements |
0.091 |
| published_at |
2026-06-06T12:55:00Z |
|
|
| url |
https://api.first.org/data/v1/epss?cve=CVE-2026-44372 |
|
| 1 |
| reference_url |
https://github.com/nitrojs/nitro |
| reference_id |
|
| reference_type |
|
| scores |
| 0 |
| value |
6.1 |
| scoring_system |
cvssv3.1 |
| scoring_elements |
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N |
|
| 1 |
| value |
5.3 |
| scoring_system |
cvssv4 |
| scoring_elements |
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N |
|
| 2 |
| value |
MODERATE |
| scoring_system |
generic_textual |
| scoring_elements |
|
|
|
| url |
https://github.com/nitrojs/nitro |
|
| 2 |
| reference_url |
https://github.com/nitrojs/nitro/pull/4236 |
| reference_id |
|
| reference_type |
|
| scores |
| 0 |
| value |
6.1 |
| scoring_system |
cvssv3.1 |
| scoring_elements |
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N |
|
| 1 |
| value |
5.3 |
| scoring_system |
cvssv4 |
| scoring_elements |
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N |
|
| 2 |
| value |
MODERATE |
| scoring_system |
generic_textual |
| scoring_elements |
|
|
| 3 |
| value |
Track |
| scoring_system |
ssvc |
| scoring_elements |
SSVCv2/E:N/A:Y/T:T/P:M/B:A/M:M/D:T/2026-05-14T15:46:57Z/ |
|
|
| url |
https://github.com/nitrojs/nitro/pull/4236 |
|
| 3 |
| reference_url |
https://github.com/nitrojs/nitro/releases/tag/v2.13.4 |
| reference_id |
|
| reference_type |
|
| scores |
| 0 |
| value |
6.1 |
| scoring_system |
cvssv3.1 |
| scoring_elements |
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N |
|
| 1 |
| value |
5.3 |
| scoring_system |
cvssv4 |
| scoring_elements |
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N |
|
| 2 |
| value |
MODERATE |
| scoring_system |
generic_textual |
| scoring_elements |
|
|
| 3 |
| value |
Track |
| scoring_system |
ssvc |
| scoring_elements |
SSVCv2/E:N/A:Y/T:T/P:M/B:A/M:M/D:T/2026-05-14T15:46:57Z/ |
|
|
| url |
https://github.com/nitrojs/nitro/releases/tag/v2.13.4 |
|
| 4 |
|
| 5 |
|
| 6 |
|
| 7 |
|
| 8 |
|
|
| fixed_packages |
|
| aliases |
CVE-2026-44372, GHSA-9phm-9p8f-hw5m
|
| risk_score |
3.1 |
| exploitability |
0.5 |
| weighted_severity |
6.2 |
| resource_url |
http://public2.vulnerablecode.io/vulnerabilities/VCID-uj7r-xwhg-nbgh |
|
| 1 |
| url |
VCID-wc44-rd7y-uqdj |
| vulnerability_id |
VCID-wc44-rd7y-uqdj |
| summary |
Nitro has a proxy scope bypass via percent-encoded path traversal in `routeRules`
A proxy route rule like:
```ts
routeRules: {
"/api/orders/**": { proxy: { to: "http://upstream/orders/**" } }
}
```
is intended to limit the proxy to URLs under `/api/orders/`. Before the patch, an attacker could bypass that scope by sending percent-encoded path traversal (`..%2f`) in the URL, causing Nitro to forward a request that the upstream resolved outside the configured scope. Example exploit:
```
GET /api/orders/..%2fadmin%2fconfig.json
```
Nitro sees `..%2f` as opaque characters at match time, the `/api/orders/**` rule matched, and the raw path was forwarded to the upstream as `/orders/..%2fadmin/config.json`. An upstream that decodes `%2F` to `/` then resolved `..` and can serve `/admin/config.json` outside the intended scope.
### Are you affected?
Users may be affected if **ALL** of the following are true:
1. Their project uses Nitro's `routeRules` with a `proxy` entry (`{ proxy: { to: "..." } }`).
2. The proxy `to` value uses a `/**` wildcard suffix to forward sub-paths.
3. The **upstream** behind the proxy decodes `%2F` as `/` before routing or filesystem lookup.
4. Proxy route rules are _not_ handled natively at CDN (nitro v3 and vercel)
Whether the bypass actually leaks data depends on the upstream. Modern JS frameworks keep `%2F` opaque per RFC 3986 and are safe by construction.
- **Safe examples:** H3 v2, Express v5, Hono v4 — modern JS frameworks keep `%2F` opaque per RFC 3986.
- **Vulnerable examples:** naive imlementations that decodes the URL, static file servers, CGI dispatchers, Python `os.path`-based routing, anything sitting behind another layer that decodes `%2F` (common in microservice meshes).
## Impact
Any HTTP path reachable from the Nitro server to the upstream could be requested, regardless of the configured `/**` scope. In typical deployments (API gateway, BFF, microservice proxy) this could expose internal admin endpoints, secrets endpoints, or other services the developer believed the scope rule fenced off.
## Patched versions
Upgrade to one of:
- [2.13.4](https://github.com/nitrojs/nitro/releases/tag/v2.13.4) or later (https://github.com/nitrojs/nitro/pull/4223)
- [3.0.260429-beta](https://github.com/nitrojs/nitro/releases/tag/v3.0.260429-beta) or later (https://github.com/nitrojs/nitro/pull/4222)
The fix canonicalizes the incoming pathname before building the upstream URL and rejects requests with `400 Bad Request` if the resolved path would escape the rule's base. The bytes forwarded upstream are unchanged when the request is allowed.
> Note: the fix assumes the upstream does not double-decode percent-encoding. If your upstream decodes twice (`%252F → %2F → /`), it remains your responsibility to harden it. **Single-decode is standard**.
## Credits
Reported by [@mHe4am](https://github.com/mHe4am) ([@he4am on HackerOne](https://hackerone.com/he4am)) via the [Vercel Open Source](https://hackerone.com/vercel-open-source?type=team) program. |
| references |
| 0 |
| reference_url |
https://api.first.org/data/v1/epss?cve=CVE-2026-44373 |
| reference_id |
|
| reference_type |
|
| scores |
| 0 |
| value |
0.00043 |
| scoring_system |
epss |
| scoring_elements |
0.13617 |
| published_at |
2026-06-07T12:55:00Z |
|
| 1 |
| value |
0.00043 |
| scoring_system |
epss |
| scoring_elements |
0.13563 |
| published_at |
2026-06-09T12:55:00Z |
|
| 2 |
| value |
0.00043 |
| scoring_system |
epss |
| scoring_elements |
0.13531 |
| published_at |
2026-06-08T12:55:00Z |
|
| 3 |
| value |
0.00043 |
| scoring_system |
epss |
| scoring_elements |
0.13659 |
| published_at |
2026-06-06T12:55:00Z |
|
| 4 |
| value |
0.00043 |
| scoring_system |
epss |
| scoring_elements |
0.13655 |
| published_at |
2026-06-05T12:55:00Z |
|
|
| url |
https://api.first.org/data/v1/epss?cve=CVE-2026-44373 |
|
| 1 |
|
| 2 |
|
| 3 |
|
| 4 |
|
| 5 |
|
| 6 |
|
| 7 |
|
| 8 |
|
|
| fixed_packages |
|
| aliases |
CVE-2026-44373, GHSA-5w89-w975-hf9q
|
| risk_score |
3.1 |
| exploitability |
0.5 |
| weighted_severity |
6.2 |
| resource_url |
http://public2.vulnerablecode.io/vulnerabilities/VCID-wc44-rd7y-uqdj |
|
|