Mar 23, 2026·6 min read·28 visits
The H3 `redirectBack()` function improperly handles protocol-relative paths in the `Referer` header. Attackers can supply a referer like `http://trusted.com//evil.com`, passing origin checks but resulting in a `Location: //evil.com` header that browsers interpret as a redirect to an external site.
A critical vulnerability in the UnJS H3 package allows attackers to bypass domain validation within the `redirectBack()` utility. By providing a maliciously crafted `Referer` header containing a protocol-relative path, attackers can force the application to issue an open redirect to an arbitrary external domain. This issue affects versions prior to v2.0.1-rc.18.
The UnJS H3 framework is a minimal HTTP framework for Node.js, extensively utilized within the Nuxt ecosystem. The framework exposes a redirectBack() utility function designed to safely redirect users back to the page specified in their Referer header. To prevent malicious redirection, this function validates that the origin of the Referer URL exactly matches the origin of the current request.
The vulnerability, classified under CWE-601 (URL Redirection to Untrusted Site), occurs because the validation logic fails to account for protocol-relative paths extracted from the WHATWG URL object. While the origin validation correctly ensures the protocol and hostname match the trusted application, the pathname property retains leading double slashes if provided in the input.
When this unvalidated pathname is concatenated and passed directly into the Location HTTP response header, the context shifts. Modern web browsers interpret a Location header beginning with // as a protocol-relative URL, instructing the browser to maintain the current scheme (e.g., HTTPS) but navigate to a completely different host. This bypasses the developer's intended domain restrictions.
The root cause of this vulnerability lies in an impedance mismatch between how the WHATWG URL constructor parses malformed paths and how web browsers interpret HTTP Location headers. When the native Node.js URL class processes a string like https://trusted-app.com//malicious-site.com/steal, it correctly identifies the protocol as https: and the host as trusted-app.com.
Because the host matches the expected origin, the application's security check (refererURL.origin === event.url.origin) evaluates to true. However, the URL constructor parses the remainder of the string, //malicious-site.com/steal, and assigns it to the pathname property without normalizing the leading slashes. The application then uses this raw pathname to construct the redirect destination.
According to RFC 3986, a path segment beginning with two slashes is a network-path reference, commonly known as a protocol-relative URL. When the server sets Location: //malicious-site.com/steal, the browser resolves this relative to the current scheme. If the user is browsing via HTTPS, the browser redirects the user to https://malicious-site.com/steal, effectively completing the Open Redirect attack.
In versions of H3 prior to v2.0.1-rc.18, the redirectBack() function extracts the pathname directly from the validated refererURL object and applies it to the Location header. The vulnerable code path assumes that since the origin is trusted, the associated path is inherently local and safe for redirection.
The patch introduced in commit 459a1c6593365b0810e9c502df7c3e82837321d7 introduces an explicit normalization step for the pathname string. The implementation now checks if the path begins with a protocol-relative sequence (//) and strips all leading slashes before prepending a single, safe forward slash.
// File: src/utils/response.ts
export function redirectBack(event, opts = {}) {
// ... existing origin validation logic ...
if (refererURL.origin === event.url.origin) {
let pathname = refererURL.pathname;
// PATCH: Sanitize protocol-relative paths
if (pathname.startsWith("//")) {
pathname = "/" + pathname.replace(/^\/+/, "");
}
location = pathname + (opts.allowQuery ? refererURL.search : "");
}
// ...
}This regex-based fix (/^\/+/) is highly effective because it ensures that regardless of how many slashes an attacker injects (e.g., ///evil.com), the resulting path is strictly forced into an absolute path relative to the current origin (e.g., /evil.com). This completely neutralizes the protocol-relative behavior in the browser's Location parser.
Exploiting this Open Redirect requires an attacker to control the Referer header sent by the victim's browser. While browsers typically restrict direct manipulation of the Referer header via client-side scripts, an attacker can construct a malicious webpage that naturally generates the desired header when the victim clicks a link.
The attack begins by hosting a staging page that initiates a request to the vulnerable H3 application endpoint. The staging environment is configured to append the malicious protocol-relative payload to its URL structure, or the attacker crafts a direct link containing the payload structure if the application passes user-controlled parameters into the Referer generation.
The following proof-of-concept test case demonstrates the exact server-side behavior. When the malicious referer http://localhost//evil.com/steal is submitted, the unpatched server responds with an unsafe Location header.
it("prevents open redirect via protocol-relative path in referer", async () => {
// Application endpoint using redirectBack
t.app.post("/submit", (event) => redirectBack(event));
const baseUrl = "http://localhost";
const res = await t.fetch("/submit", {
method: "POST",
headers: {
referer: `${baseUrl}//evil.com/steal`
},
});
// Unpatched response returns Location: //evil.com/steal
// Patched response returns Location: /evil.com/steal
});The primary impact of this vulnerability is the facilitation of highly convincing phishing campaigns. Because the initial URL points to a trusted domain (the application running H3), users and email security filters are significantly more likely to trust the link. Once clicked, the application transparently forwards the user to an attacker-controlled destination.
Beyond basic phishing, Open Redirects often serve as chaining primitives in more complex attack sequences. If the vulnerable application utilizes OAuth or similar token-based authentication flows, an attacker can manipulate the redirect to hijack authorization codes or access tokens. By appending token fragments to the redirected URL, the attacker captures sensitive credentials on their own infrastructure.
The vulnerability is assessed with a CVSS 3.1 score of 6.1 (Medium). The attack vector is Network (AV:N) with Low attack complexity (AC:L), requiring no specialized privileges (PR:N). However, it strictly requires User Interaction (UI:R) and affects the changed scope of the user's browsing session (S:C), leading to low impacts on Confidentiality and Integrity (C:L/I:L).
The definitive remediation for this vulnerability is upgrading the h3 package to version v2.0.1-rc.18 or later. Development teams should audit their package.json or package-lock.json files to ensure all transitive dependencies utilizing h3 are updated to incorporate the patched logic.
For environments where immediate patching is not technically feasible, a temporary mitigation involves deploying middleware or a Web Application Firewall (WAF) rule to intercept and sanitize incoming requests. Specifically, rules should inspect the Referer header and reject or rewrite any requests where the pathname segment begins with multiple forward slashes.
Developers utilizing redirectBack() should also review their application architecture to determine if relying on the Referer header is strictly necessary. Implementing stateful redirection flows using server-side session variables or signed redirect tokens provides a more robust defense-in-depth posture against redirection attacks.
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
h3 UnJS | < v2.0.1-rc.18 | v2.0.1-rc.18 |
| Attribute | Detail |
|---|---|
| Vulnerability Class | Open Redirect (CWE-601) |
| CVSS v3.1 Score | 6.1 (Medium) |
| Attack Vector | Network |
| Authentication Required | None |
| User Interaction | Required |
| Affected Component | redirectBack() utility |
| Exploit Status | Proof of Concept Available |
A web application accepts a user-controlled input that specifies a link to an external site, and uses that link in a Redirect. This simplifies phishing attacks.
A critical authentication bypass and context spoofing vulnerability exists in Traefik's BasicAuth, DigestAuth, and ForwardAuth middlewares prior to versions 2.11.51, 3.6.22, and 3.7.6. The flaw arises because Traefik's header cleanup mechanisms rely on Go's standard library header canonicalization, which does not modify or delete headers containing underscores. Consequently, unauthenticated remote attackers can inject custom underscore-variant headers (e.g., X_Auth_User) that bypass Traefik's stripping filters and reach backend application servers. When downstream backends normalize both hyphens and underscores into the same environment variables, the attacker's spoofed identity value is processed as trusted authorization data.
CVE-2026-71324 is a high-severity HTTP request smuggling vulnerability in the Traefik reverse proxy. It allows an unauthenticated remote attacker to achieve cross-user response poisoning when Traefik is configured to route HTTP/2 or HTTP/3 CONNECT requests to an HTTP/1.1 upstream backend. By sending a crafted CONNECT request that is subsequently rejected by the backend with a keep-alive non-2xx response, the attacker can leave smuggled requests within the shared connection pool, which are then served to subsequent clients.
A critical process-fatal NULL pointer dereference vulnerability exists in the WebDAV backend of rclone (when configured with ownCloud Infinite Scale TUS uploads). During transport failures, a nil HTTP response pointer is dereferenced directly without validation, leading to an unhandled Go runtime panic that terminates the entire rclone daemon. This vulnerability was resolved in rclone version 1.75.0.
A path traversal vulnerability exists in the S3 emulation layer of rclone when executing the 'serve s3' subcommand. Because the application maps client-supplied S3 object keys containing relative directory sequences to file paths without proper boundary checks, an attacker can escape the logical containment of a target bucket. This enables unauthorized reading, writing, and deletion of files at the root level of the served storage directory.
A critical security flaw was identified in rclone before version 1.75.0, where the custom S3 redirect handler failed to sanitize sensitive authentication headers and encryption keys during cross-host redirects or transport downgrades. This flaw allows attackers on the path or controlling target hosts to intercept sensitive IBM IAM tokens, AWS S3 Express tokens, and customer-provided server-side encryption keys (SSE-C).
A protocol-level CRLF injection vulnerability exists in rclone's FTP backend before version 1.75.0. When configured with a non-default filename encoding, rclone allows carriage return and line feed characters to pass directly into the underlying FTP client library. Because the library constructs line-oriented control commands without input validation, an attacker-controlled filename can inject arbitrary FTP commands into the session, allowing unauthorized file deletion and modification on the target server.