h3 (Unjs), Open Redirect via Protocol-Relative Paths in redirectBack() (Medium)

Listen to this Post

How the mentioned CVE works

The vulnerability exists in h3’s `redirectBack()` helper which is designed to redirect users back to the URL provided in the `Referer` header after a POST request, but only if the referer’s origin matches the current request origin.
The function parses the referer using the WHATWG URL API, checks refererURL.origin === event.url.origin, and then uses `refererURL.pathname` as the redirect location.
The root cause is a mismatch between how the URL parser handles a path that begins with `//` and how browsers interpret such a location header.
When a referer contains a double slash in the path (e.g., http://target.com//evil.com/page`), the origin comparison passes because `origin` remainshttp://target.com`.

However, `pathname` is extracted as `”//evil.com/page”`.

This pathname is concatenated into the `Location` header unchanged.
Browsers treat a `Location: //evil.com/page` header as a protocol-relative URL, meaning they automatically use the same protocol as the current page (e.g., https) and redirect to evil.com.
An attacker can craft a link like http://target.com//evil.com/page`.
If the target application uses catch‑all routing (common in SPAs built with h3/Nitro), the page loads normally, and any subsequent use of `redirectBack()` will read the malicious referer, pass the origin check, and redirect the victim to an external attacker‑controlled domain.
This bypasses the intended origin restriction and turns `redirectBack()` into an open redirect primitive.
The vulnerability is present in all h3 versions that include the flawed implementation before the patch was applied.
<h2 style="color: blue;">dailycve form</h2>
Platform: h3 (Unjs)
Version: < fixed version
Vulnerability: Open redirect
Severity: Medium
date: 2026-03-24
<h2 style="color: blue;">Prediction: Already patched in v1.12.0</h2>
<h2 style="color: blue;">Analytics under heading What Undercode Say:</h2>

PoC: Minimal h3 app demonstrating the redirect
cat > /tmp/h3-redirect-poc.ts << 'SCRIPT'
import { H3, redirectBack } from "h3";
const app = new H3();
app.post("/submit", (event) => redirectBack(event));
const res = await app.fetch(new Request("http://localhost/submit", {
method: "POST",
headers: { referer: "http://localhost//evil.com/steal" }
}));
console.log("Status:", res.status);
console.log("Location:", res.headers.get("location"));
Expected: a same-origin path, Actual: "//evil.com/steal"
SCRIPT
Verify URL parsing behavior
node -e "
const u = new URL('http://localhost//evil.com/steal');
console.log('origin:', u.origin); // http://localhost
console.log('pathname:', u.pathname); // //evil.com/steal
console.log('origin matches:', u.origin === 'http://localhost'); // true
"

<h2 style="color: blue;">Exploit:</h2>
1. Attacker crafts a link to the vulnerable application:
https://trusted.com//evil.com/phish`.
2. Victim clicks the link and visits the trusted domain (the double‑slash is part of the path).
3. While on the site, the victim triggers an endpoint that calls `redirectBack()` (e.g., submits a form).
4. The browser sends Referer: https://trusted.com//evil.com/phish`.
5. The server verifies origin (
https://trusted.com`) passes, and sets Location: //evil.com/phish.
6. Victim’s browser follows the protocol‑relative redirect to evil.com, where a phishing page steals credentials.

Protection from this CVE

  • Upgrade h3 to version 1.12.0 or later, where `redirectBack()` sanitises paths that begin with //.
  • If upgrading is not possible, apply the following patch to src/utils/response.ts:
    let pathname = refererURL.pathname;
    if (pathname.startsWith("//")) {
    pathname = "/" + pathname.replace(/^\/+/, "");
    }
    location = pathname + (opts.allowQuery ? refererURL.search : "");
    
  • As a workaround, avoid using `redirectBack()` on endpoints where the referer may be attacker‑controlled, or manually validate the referer path.

Impact

  • Phishing – Redirects to a lookalike domain to harvest credentials.
  • OAuth token theft – In OAuth flows using redirectBack(), an attacker can steal authorization codes.
  • Loss of trust – Users see the initial link points to a legitimate domain, reducing suspicion.
  • No authentication required – Any endpoint using `redirectBack()` is vulnerable without any prior authentication.

🎯Let’s Practice Exploiting & Learn Patching For Free:

Sources:

Reported By: github.com
Extra Source Hub:
Undercode

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top