CVE-2025-6429
Overview
Background
- `nsIURI::GetSpec` vs `GetPrePath`
GetSpecreturns the entire serialized URI (scheme + authority/host + path + query).GetPrePathreturns only thescheme://host[:port]prefix; the path/query is a separate component (pathin the patched code).- String rewrite ops
- The routine runs
FindChar('&'/'?'),ReplaceChar('?','&'),SetCharAt, andReplaceSubstring("/v/","/embed/")over the URL text before re-parsing it withNewURIWithDocumentCharset. - Embed domain restrictions
- Sites may restrict which domains can be embedded; the rewrite result determines the effective embedded origin.
Root Cause Analysis
The old code fetched the whole URL with aURI->GetSpec(uri) and then performed all of its character searches and substring replacements over that single string — including scheme and host. Because the search for &/? and the "/v/" → "/embed/" replacement operated on the complete spec, a crafted URL whose authority or path was arranged so these operations matched in the host region (or shifted the ?/& boundary) could be mutated such that, after re-parsing with NewURIWithDocumentCharset, the effective host became youtube.com. In other words, the rewrite incorrectly reinterpreted parts of the URL and could relocate the domain, letting an attacker produce a rewritten embed URL on the youtube.com origin from an input that was not genuinely a youtube.com URL — bypassing site checks that gate which domains may be embedded.
The patch separates the immutable authority from the mutable path: it replaces GetSpec(uri) with GetPrePath(prePath), and performs every FindChar, ReplaceChar, SetCharAt, and ReplaceSubstring("/v/","/embed/") operation on the path component only. The final URL is reconstructed by concatenating the untouched prePath with the rewritten path (NS_ConvertUTF8toUTF16 utf16URI(prePath); AppendUTF8toUTF16(path, utf16URI);). Keeping the scheme/host out of the string surgery means the rewrite can no longer alter the origin. The advisory (CWE-116, improper neutralization) and the diff agree that the root cause is performing origin-affecting string manipulation over the full URL spec instead of the path alone.
&/? and /v/→/embed/ string surgery over the entire URL spec including scheme and host, so a crafted input could be mutated into a youtube.com-origin URL; the fix confines all edits to the path component and keeps the pre-path (origin) untouched.Attack Path
- Craft embed
Attacker supplies an
<embed>/<object>whose URL is constructed so the rewrite’s char/substring operations misfire across the authority/path boundary. (web-reachable) - Trigger rewrite
Object loading invokes
MaybeRewriteYoutubeEmbed, which reads the full spec and runs its replacements over it. - Origin relocation
The
/v/→/embed/replacement and?/&juggling mutate the string such that re-parsing yields an effective host ofyoutube.com. - Bypass check A site that restricts embeddable domains is tricked: the resource is now treated as a youtube.com embed despite the original URL not being a legitimate youtube.com resource.
- Primitive Bypass of embed-domain restrictions, loading content under/as the youtube.com origin against the site’s intent (integrity impact, CVSS 6.5).
Impact Assessment
<embed>/<object> tag (UI:R). The gained capability is a logic/parsing bypass: an attacker can cause a URL to be rewritten to the youtube.com domain and thereby evade a site’s restriction on which domains may be embedded. It is not memory corruption and not direct code execution; the impact is an integrity-level security-check bypass whose severity depends on how the targeted site relies on embed-domain gating.Changed Functions
| Function | Change | Notes |
|---|---|---|
ifdom/base/nsObjectLoadingContent.cpp |
modified |
Files Changed
dom/base/nsObjectLoadingContent.cpp
Audit Directions
- Spec-wide string surgery on URIsSearch for other code that calls
GetSpecand then doesReplace*/FindChar/SetCharAtbefore re-parsing; such patterns can relocate the authority. - URL rewriting / canonicalization pathsAudit other legacy embed/compat rewriters and redirect builders for operating on whole specs rather than components.
- Re-parse trust boundariesReview
NewURIWithDocumentCharsetcallers that feed it a string assembled from partially-attacker-controlled fragments.
Patch
diff --git a/dom/base/nsObjectLoadingContent.cpp b/dom/base/nsObjectLoadingContent.cpp
index 26419de69eb..45549fceffe 100644
--- a/dom/base/nsObjectLoadingContent.cpp
+++ b/dom/base/nsObjectLoadingContent.cpp
@@ -539,8 +539,8 @@ void nsObjectLoadingContent::MaybeRewriteYoutubeEmbed(nsIURI* aURI,
}
// See if requester is planning on using the JS API.
- nsAutoCString uri;
- nsresult rv = aURI->GetSpec(uri);
+ nsAutoCString prePath;
+ nsresult rv = aURI->GetPrePath(prePath);
if (NS_FAILED(rv)) {
return;
}
@@ -551,10 +551,10 @@ void nsObjectLoadingContent::MaybeRewriteYoutubeEmbed(nsIURI* aURI,
// URLs, convert the parameters to query in order to make the video load
// correctly as an iframe. In either case, warn about it in the
// developer console.
- int32_t ampIndex = uri.FindChar('&', 0);
+ int32_t ampIndex = path.FindChar('&', 0);
bool replaceQuery = false;
if (ampIndex != -1) {
- int32_t qmIndex = uri.FindChar('?', 0);
+ int32_t qmIndex = path.FindChar('?', 0);
if (qmIndex == -1 || qmIndex > ampIndex) {
replaceQuery = true;
}
@@ -570,19 +570,21 @@ void nsObjectLoadingContent::MaybeRewriteYoutubeEmbed(nsIURI* aURI,
return;
}
- nsAutoString utf16OldURI = NS_ConvertUTF8toUTF16(uri);
+ NS_ConvertUTF8toUTF16 utf16OldURI(prePath);
+ AppendUTF8toUTF16(path, utf16OldURI);
// If we need to convert the URL, it means an ampersand comes first.
// Use the index we found earlier.
if (replaceQuery) {
// Replace question marks with ampersands.
- uri.ReplaceChar('?', '&');
+ path.ReplaceChar('?', '&');
// Replace the first ampersand with a question mark.
- uri.SetCharAt('?', ampIndex);
+ path.SetCharAt('?', ampIndex);
}
// Switch out video access url formats, which should possibly allow HTML5
// video loading.
- uri.ReplaceSubstring("/v/"_ns, "/embed/"_ns);
- nsAutoString utf16URI = NS_ConvertUTF8toUTF16(uri);
+ path.ReplaceSubstring("/v/"_ns, "/embed/"_ns);
+ NS_ConvertUTF8toUTF16 utf16URI(prePath);
+ AppendUTF8toUTF16(path, utf16URI);
rv = nsContentUtils::NewURIWithDocumentCharset(aRewrittenURI, utf16URI, doc,
aBaseURI);
if (NS_FAILED(rv)) {