
PEACH
Un cadre d’isolation des locataires
The fix for CVE-2026-44373 (GHSA-5w89-w975-hf9q) added isPathInScope() so a proxy route rule with a /** target rejects requests whose canonical path leaves the rule's base. The check validates a canonicalized form of the incoming request path.
Nitro then forwards a different value: the raw path with the base stripped by withoutBase() and joined under the target base. Two payload shapes pass the check while the forwarded path still contains a ..%2F that an upstream resolves outside the configured target prefix:
// segment: GET /api//..%2fadmin. The check resolves .. against the empty segment (/api//../admin → /api/admin, in scope). withoutBase then removes the empty segment and forwards /safe/..%2fadmin, which the upstream resolves to /admin. Chaining (//..%2f//..%2f…) climbs several levels, up to the upstream root.GET /proxy/..%2fproxy%2fadmin. The canonical path /proxy/admin is in scope for /proxy. Nitro forwards /safe/..%2Fproxy%2Fadmin, which the upstream resolves to /proxy/admin, outside /safe. This works whenever the public prefix and the target prefix differ.Affected code (nitropack v2):
src/runtime/internal/route-rules-utils.ts, isPathInScope(): pre-decodes %2f/%5c, then lets new URL() resolve dot segments. Empty segments are kept and consumed by ...src/runtime/internal/route-rules.ts, proxy branch: after the check passes it forwards joinURL(target.slice(0, -3), withoutBase(event.path, strpBase)). That is the raw request path, not the value that was validated.src/runtime/internal/route-rules.ts, redirect branch: same check-then-forward pattern.
The check validates the request path against the rule base, but nothing validates the final upstream URL against the target base. Any difference between the two readings can be exploited.Config:
export default defineNitroConfig({
routeRules: {
"/api/**": { proxy: { to: "http://127.0.0.1:8080/safe/**" } },
"/proxy/**": { proxy: { to: "http://127.0.0.1:8080/safe/**" } },
},
});The upstream is any server that decodes %2F once and then normalizes, for example Python's http.server.
Request (curl --path-as-is) | Forwarded upstream | Upstream resolves | Result |
|---|---|---|---|
/api/hello | /safe/hello | /safe/hello | 200 (normal) |
/api/..%2fadmin | — | — | 400 (original CVE, blocked) |
/api//..%2fadmin | /safe/..%2fadmin | /admin | 200, bypass |
/api//%2e%2e%2fadmin | /safe/%2e%2e%2fadmin | /admin | 200, bypass |
/api/orders//..%2f//..%2f//..%2froot-secret.json (rule /api/orders/** → /orders/**) | /orders/..%2f//..%2f//..%2froot-secret.json | /root-secret.json | 200, bypass |
/proxy/..%2fproxy%2fadmin | /safe/..%2fproxy%2fadmin | /proxy/admin | 200, bypass |
An unauthenticated remote attacker can make Nitro forward requests to upstream paths outside the path prefix that a /** proxy rule is meant to confine forwarding to, such as internal or admin endpoints on the same upstream. The HTTP method and body are forwarded, so both reads and state-changing requests are possible.
Wildcard redirect rules have the same scope gap, but there the result is only a redirect to another same-origin path outside the rule's target prefix.
You are affected only if all of these are true:
proxy route rule whose target ends in /** and has a non-root path prefix;%2F and resolves dot segments (many do, including Python http.server and some static servers and frameworks);Fixed in nitropack 2.13.6. Nitro now validates the final upstream (or redirect) URL against the rule's target base, after the forwarded path has been built.
If you cannot upgrade:
%2F) and dot segments in paths;Source: NVD
Évaluation gratuite des vulnérabilités
Évaluez vos pratiques de sécurité cloud dans 9 domaines de sécurité afin d’évaluer votre niveau de risque et d’identifier les lacunes dans vos défenses.
Obtenez une démo personnalisée
"La meilleure expérience utilisateur que j’ai jamais vue, offre une visibilité totale sur les workloads cloud."
"Wiz fournit une interface unique pour voir ce qui se passe dans nos environnements cloud."
"Nous savons que si Wiz identifie quelque chose comme critique, c’est qu’il l’est réellement."