[10] XMLSerializer Extension URL Leak
Severity: Medium | Component: WebCore XML serialization | 0f4832c
Rated Medium because the observable effect is trivial extension fingerprinting from any web page via a single JavaScript call, but the impact is limited to information disclosure (extension identity) without memory corruption or code execution.
Fix the bug by masking out custom scheme URLs in XMLSerializer.
Source/WebCore/xml/XMLSerializer.cpp
String XMLSerializer::serializeToString(Node& node)
{
- return serializeFragment(node, SerializedNodes::SubtreeIncludingNode, nullptr, ResolveURLs::No, SerializationSyntax::XML);
+ return serializeFragment(node, SerializedNodes::SubtreeIncludingNode, nullptr, ResolveURLs::NoExcludingURLsForPrivacy, SerializationSyntax::XML);
}
Tools/TestWebKitAPI/Tests/WebKitCocoa/WKWebViewConfiguration.mm
+ NSString *xmlSource = [webView stringByEvaluatingJavaScript:@"(new XMLSerializer()).serializeToString(document.body)"];
+ EXPECT_WK_STREQ(xmlSource, @"<body xmlns=\"http://www.w3.org/1999/xhtml\"><iframe src=\"webkit-masked-url://hidden/\"></iframe><iframe src=\"http://apple.com/baz.html\"></iframe></body>");
Missing privacy-URL masking on an alternative DOM serialization path.
Patch Details
The change is minimal: XMLSerializer::serializeToString now passes ResolveURLs::NoExcludingURLsForPrivacy instead of ResolveURLs::No when calling serializeFragment. This causes custom scheme URLs (used by web extensions) to be replaced with webkit-masked-url://hidden/ in the serialized output. The test confirms that XMLSerializer output now masks extension URLs while preserving normal http:// URLs.
Background
WebKit supports masked URL schemes as a privacy mechanism: when a web extension injects content using a custom URL scheme (e.g., another-scheme://foo.com/bar.js), the browser can be configured to replace these URLs with webkit-masked-url://hidden/ during DOM serialization. This prevents web pages from discovering which extensions are installed — a common fingerprinting vector. The ResolveURLs enum controls this behavior: ResolveURLs::No serializes URLs verbatim, while ResolveURLs::NoExcludingURLsForPrivacy preserves relative URLs but masks private custom scheme URLs. The innerHTML serialization path already used the privacy-aware variant.
Analysis
The root cause is a bypass-via-alternative-path: a privacy mechanism was applied to innerHTML serialization but not to XMLSerializer, which ultimately calls the same serializeFragment function with a different enum value. Any web page could call new XMLSerializer().serializeToString(document.body) to recover the real custom scheme URLs of installed browser extensions, leaking information about which extensions are installed and their internal URL structures.
Aaa Aaaaaaa Aa Aaaaaaaa a Aaaaaa Aaaaaaaaaa Aaaa Aa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aa Aaa Aaaa Aaaaaaaaaaa Aaaaaaaaaaaaaaaaaa Aaaaaaaaa Aaaaaaa Aaa Aaaaaaaa Aaaaaa Aaaaaa Aaaaa Aaaaaaaaa Aaaaaaaaaaaaaa Aaa Aa Aaaa Aaa Aaaaaaaa Aaaaaaa Aaaaaaaaaaaa Aaaaaaaaaa Aaaaaaaaa Aaaaaaaaaa Aaaa Aaaaaaaa Aaaa Aaa Aa Aaaaaaaaa Aaaaaaaaaa Aa a Aaaaaaaaaaaa Aaaaaaa Aaaaaaaaaaaaa Aa Aaaaaaaa Aaaaaaaaaaaa Aaaaaa Aaaaaaaaaaa Aaaaa Aa Aaaaaaaa Aaaaa Aaaaaaaaaa
Aaaa Aaaaaaaaaaaaa Aaaaaaa Aaaa Aaaaaaa Aa Aaaaaaa Aaa Aaaaaaaaa Aaaaaaaaa Aaaaaaaa a Aaaaaaaa Aa Aaaaaaa Aaaaaaaa Aa Aaaaaaaa Aa a Aaaaaaaaaaaaa Aaaaaaaaa Aaaaa Aaaaaaaaaaaaa Aaaa Aaaa Aa Aaaaaaa a Aaa Aaaa Aaa Aaaa Aaaaaa Aaaa Aaaa Aa Aaa Aaaa Aaaaa Aa Aaaaaa Aaaa Aaaa Aaa Aaaaaaaaaaa Aaaaaa Aaaaaaaaa Aaaaaa Aaaaaaaaa Aaaaaaaa
Audit directions
a Aaaaaaaa Aaaaaaaaaaaaaaaa Aaaaaa Aaaaaaa Aa Aaa Aaaaaaaaaaaaa Aaaa Aaa Aaaaaa Aa Aa Aaaaaaaaaaa Aaaa Aaaa Aaaa Aaa Aaaa Aaaaaaaaaa Aaaaaaaa Aaaa Aaaaaaaaa Aaaaaaaaaaa Aaaaa Aaa Aaaaaaa Aa Aaaaaaaaaaaaaaaaaaa Aa Aaaaaaa Aa Aaaaaa Aaaa Aaaa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Aaaa Aaa Aaaaaa Aaaaa Aa Aaaaaaaaaa Aa Aaa Aaaaaaaa Aaaa Aaa Aaaaaaaaaaaaaaaaaaa Aaa Aaaaaaaaaaaaaaaaa Aaaaaa Aaa Aaaaaaaa Aa Aaaa Aaaaa Aaaaaaaaa Aaaaaa Aaaaaa
a Aaaaaaaa Aaaaaaaaa Aaaaaaaaaaaaaa Aaa Aaa Aaaaaaaaaaa Aaaaa Aaaaaa Aaaaaaaaaaaaaa Aaaaa Aaaaaaa Aaaaa Aaaa Aaaa Aaaaaa Aaa Aaaaaaa Aaaaaa Aaaaaaaaaaaaaaaaaa Aaa Aaaaaaaaaaaaaaaa Aaaaa Aaaaaaaaaaaaaaaaaaaaaaaaaa Aaa Aaaaaaaa Aaaaa Aaaaaaaaaaaaaaaaaaaaaa Aaa Aaaaaaaaaa Aaaaaa Aaaa Aaaaa Aaa Aaaaaaaaaa Aaaaaaaaaa Aaaaaa Aaa Aaaa Aa Aaaaaa Aaaaaa Aaaa Aa Aaaaaaaa Aaaaaaa Aaaaa Aaaa Aaaaaaa Aaaaaaa Aaa Aaaaa