Firefox · Networking
CVE-2026-117966
Logic Error in Networking
Overview
Moderate
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
onStartRequestnetwerk/test/browser/browser_alt_data_cross_origin.js |
modified | |
onDataAvailablenetwerk/test/browser/browser_alt_data_cross_origin.js |
modified | |
onStopRequestnetwerk/test/browser/browser_alt_data_cross_origin.js |
modified | |
add_tasknetwerk/test/browser/browser_alt_data_cross_origin.js |
modified |
Files Changed
netwerk/test/browser/browser_alt_data_cross_origin.js
Patch
diff --git a/netwerk/test/browser/browser_alt_data_cross_origin.js b/netwerk/test/browser/browser_alt_data_cross_origin.js
index 43ce432ca16..b7076dd6e27 100644
--- a/netwerk/test/browser/browser_alt_data_cross_origin.js
+++ b/netwerk/test/browser/browser_alt_data_cross_origin.js
@@ -64,6 +64,57 @@ async function writeAltDataTask(url, altType, altContent) {
os.close();
}
+// Content-process task: like writeAltDataTask, but the channel claims
+// `forgedOrigin` as its loading and triggering principal, as a compromised
+// content process could. The document's cookie jar settings are reused so the
+// load shares a cache entry with `forgedOrigin` iframes in this document.
+async function writeForgedAltDataTask(url, altType, altContent, forgedOrigin) {
+ const { NetUtil } = ChromeUtils.importESModule(
+ "resource://gre/modules/NetUtil.sys.mjs"
+ );
+ const forged =
+ Services.scriptSecurityManager.createContentPrincipalFromOrigin(
+ forgedOrigin
+ );
+
+ const chan = NetUtil.newChannel({
+ uri: url,
+ loadingPrincipal: forged,
+ triggeringPrincipal: forged,
+ securityFlags: Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_INHERITS_SEC_CONTEXT,
+ contentPolicyType: Ci.nsIContentPolicy.TYPE_SCRIPT,
+ });
+ chan.loadInfo.cookieJarSettings = content.document.cookieJarSettings;
+
+ const handle = await new Promise(resolve => {
+ chan.asyncOpen({
+ QueryInterface: ChromeUtils.generateQI([
+ "nsIStreamListener",
+ "nsIRequestObserver",
+ ]),
+ onStartRequest() {},
+ onDataAvailable(request, stream, offset, count) {
+ const s = Cc["@mozilla.org/scriptableinputstream;1"].createInstance(
+ Ci.nsIScriptableInputStream
+ );
+ s.init(stream);
+ s.read(count);
+ },
+ onStopRequest(request) {
+ resolve(
+ request
+ .QueryInterface(Ci.nsICacheInfoChannel)
+ .getCacheEntryWriteHandle()
+ );
+ },
+ });
+ });
+
+ const os = handle.openAlternativeOutputStream(altType, altContent.length);
+ os.write(altContent, altContent.length);
+ os.close();
+}
+
// Content-process task: cache-only read of `url` preferring alt-data. Returns
// { altType, buffer, status, partitionKey }.
async function readAltDataTask(url, altType) {
@@ -171,3 +222,42 @@ add_task(async function test_cross_origin_alt_data_is_rejected() {
);
});
});
+
+// A content process must not be able to bind alt-data to another origin by
+// claiming that origin's principal for the load that writes it.
+add_task(async function test_forged_principal_alt_data_is_rejected() {
+ const url = RESOURCE_URL + "?forged";
+ await BrowserTestUtils.withNewTab(PAGE_A, async browser => {
+ await SpecialPowers.spawn(
+ browser,
+ [url, ALT_TYPE, ALT_CONTENT, new URL(IFRAME_B).origin],
+ writeForgedAltDataTask
+ );
+
+ await SpecialPowers.spawn(browser, [IFRAME_B], async iframeUrl => {
+ const iframe = content.document.createElement("iframe");
+ const loaded = new Promise(resolve =>
+ iframe.addEventListener("load", resolve, { once: true })
+ );
+ iframe.src = iframeUrl;
+ content.document.body.appendChild(iframe);
+ await loaded;
+ });
+
+ const res = await SpecialPowers.spawn(
+ browser.browsingContext.children[0],
+ [url, ALT_TYPE],
+ readAltDataTask
+ );
+ ok(
+ Components.isSuccessCode(res.status),
+ "the read is a cache hit (LOAD_ONLY_FROM_CACHE)"
+ );
+ is(
+ res.altType,
+ "",
+ "alt-data written under a forged principal must NOT be served"
+ );
+ is(res.buffer, ORIGINAL, "the read gets the original script instead");
+ });
+});
Loading diff…
References
On This Page