Firefox · Toolkit
CVE-2026-8966
Logic Error in Toolkit
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
iftoolkit/components/ipprotection/IPPChannelFilter.sys.mjs |
modified | |
add_tasktoolkit/components/ipprotection/tests/xpcshell/test_IPPChannelFilter.js |
modified | |
fortoolkit/components/ipprotection/tests/xpcshell/test_IPPChannelFilter.js |
modified |
Files Changed
toolkit/components/ipprotection/IPPChannelFilter.sys.mjstoolkit/components/ipprotection/tests/xpcshell/test_IPPChannelFilter.js
Patch
diff --git a/toolkit/components/ipprotection/IPPChannelFilter.sys.mjs b/toolkit/components/ipprotection/IPPChannelFilter.sys.mjs
index 36d41b8c577..24bcf827994 100644
--- a/toolkit/components/ipprotection/IPPChannelFilter.sys.mjs
+++ b/toolkit/components/ipprotection/IPPChannelFilter.sys.mjs
@@ -337,17 +337,16 @@ export class IPPChannelFilter {
if (!["http", "https"].includes(uri.scheme)) {
return true;
}
+ let principal =
+ channel.loadInfo?.loadingPrincipal ||
+ Services.scriptSecurityManager.getChannelURIPrincipal(channel);
- if (IPPChannelFilter.isLocal(uri)) {
+ if (IPPChannelFilter.isLocal(principal)) {
return true;
}
const origin = uri.prePath; // scheme://host[:port]
- let principal =
- channel.loadInfo?.loadingPrincipal ||
- Services.scriptSecurityManager.getChannelURIPrincipal(channel);
-
let hasExclusion = lazy.IPPExceptionsManager.hasExclusion(principal);
if (hasExclusion) {
@@ -370,28 +369,12 @@ export class IPPChannelFilter {
return new MatchPatternSet(patterns, MATCH_PATTERN_OPTIONS);
}
- static isLocal(uri) {
- if (Services.io.hostnameIsLocalIPAddress(uri)) {
- return true;
- }
-
- const hostname = uri.host;
- return (
- /^(.+\.)?localhost$/.test(hostname) ||
- /^(.+\.)?localhost6$/.test(hostname) ||
- /^(.+\.)?localhost.localdomain$/.test(hostname) ||
- /^(.+\.)?localhost6.localdomain6$/.test(hostname) ||
- // https://tools.ietf.org/html/rfc2606
- /\.example$/.test(hostname) ||
- /\.invalid$/.test(hostname) ||
- /\.test$/.test(hostname) ||
- // https://tools.ietf.org/html/rfc8375
- /^(.+\.)?home\.arpa$/.test(hostname) ||
- // https://tools.ietf.org/html/rfc6762
- /\.local$/.test(hostname) ||
- // Loopback
- /^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(hostname)
- );
+ /**
+ *
+ * @param {nsIPrincipal} principal
+ */
+ static isLocal(principal) {
+ return principal.isLoopbackHost || principal.isLocalIpAddress;
}
/**
diff --git a/toolkit/components/ipprotection/tests/xpcshell/test_IPPChannelFilter.js b/toolkit/components/ipprotection/tests/xpcshell/test_IPPChannelFilter.js
index 5eaab390244..bcaeccc2dd6 100644
--- a/toolkit/components/ipprotection/tests/xpcshell/test_IPPChannelFilter.js
+++ b/toolkit/components/ipprotection/tests/xpcshell/test_IPPChannelFilter.js
@@ -555,40 +555,46 @@ add_task(
);
add_task(async function test_local_connections() {
+ const makePrincipal = url =>
+ Services.scriptSecurityManager.createContentPrincipal(
+ Services.io.newURI(url),
+ {}
+ );
+
const tests = [
+ // True either LAN or Loopback
+ ["http://[::]", true],
+ ["http://[::1]", true],
+ ["http://[::1]:1234", true],
+ ["http://[::ffff:0:0]", true],
+ ["http://127.0.0.1", true],
+ ["http://127.1.2.3", true],
+ ["http://10.1.2.3", true],
+ ["http://192.168.0.1", true],
+ ["http://169.254.0.1", true],
["http://localhost", true],
- ["http://looocalhost", false],
["http://something.localhost", true],
+ // False, anything else
+ ["http://something.test", false],
+ ["http://looocalhost", false],
["http://localhost.something", false],
- ["http://localhost6", true],
+ ["http://localhost6", false],
["http://looocalhost6", false],
- ["http://something.localhost6", true],
+ ["http://something.localhost6", false],
["http://localhost6.something", false],
- ["http://something.example", true],
+ ["http://something.example", false],
["http://example.com", false],
- ["http://something.invalid", true],
+ ["http://something.invalid", false],
["http://invalid.com", false],
- ["http://something.test", true],
["http://test.com", false],
- ["http://127.0.0.1", true],
- ["http://127.1.2.3", true],
["http://128.1.2.3", false],
- ["http://169.254.0.1", true],
["http://169.253.0.1", false],
- ["http://192.168.0.1", true],
["http://193.168.0.1", false],
- ["http://10.1.2.3", true],
["http://11.1.2.3", false],
- ["http://[::]", true],
- ["http://[::ffff:0:0]", true],
];
- for (const [uri, isLocal] of tests) {
- Assert.equal(
- IPPChannelFilter.isLocal(Services.io.newURI(uri)),
- isLocal,
- uri
- );
+ for (const [url, isLocal] of tests) {
+ Assert.equal(IPPChannelFilter.isLocal(makePrincipal(url)), isLocal, url);
}
});
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/toolkit/components/ipprotection/tests/xpcshell/test_IPPChannelFilter.js b/toolkit/components/ipprotection/tests/xpcshell/test_IPPChannelFilter.js
index 5eaab390244..bcaeccc2dd6 100644
--- a/toolkit/components/ipprotection/tests/xpcshell/test_IPPChannelFilter.js
+++ b/toolkit/components/ipprotection/tests/xpcshell/test_IPPChannelFilter.js
@@ -555,40 +555,46 @@ add_task(
);
add_task(async function test_local_connections() {
+ const makePrincipal = url =>
+ Services.scriptSecurityManager.createContentPrincipal(
+ Services.io.newURI(url),
+ {}
+ );
+
const tests = [
+ // True either LAN or Loopback
+ ["http://[::]", true],
+ ["http://[::1]", true],
+ ["http://[::1]:1234", true],
+ ["http://[::ffff:0:0]", true],
+ ["http://127.0.0.1", true],
+ ["http://127.1.2.3", true],
+ ["http://10.1.2.3", true],
+ ["http://192.168.0.1", true],
+ ["http://169.254.0.1", true],
["http://localhost", true],
- ["http://looocalhost", false],
["http://something.localhost", true],
+ // False, anything else
+ ["http://something.test", false],
+ ["http://looocalhost", false],
["http://localhost.something", false],
- ["http://localhost6", true],
+ ["http://localhost6", false],
["http://looocalhost6", false],
- ["http://something.localhost6", true],
+ ["http://something.localhost6", false],
["http://localhost6.something", false],
- ["http://something.example", true],
+ ["http://something.example", false],
["http://example.com", false],
- ["http://something.invalid", true],
+ ["http://something.invalid", false],
["http://invalid.com", false],
- ["http://something.test", true],
["http://test.com", false],
- ["http://127.0.0.1", true],
- ["http://127.1.2.3", true],
["http://128.1.2.3", false],
- ["http://169.254.0.1", true],
["http://169.253.0.1", false],
- ["http://192.168.0.1", true],
["http://193.168.0.1", false],
- ["http://10.1.2.3", true],
["http://11.1.2.3", false],
- ["http://[::]", true],
- ["http://[::ffff:0:0]", true],
];
- for (const [uri, isLocal] of tests) {
- Assert.equal(
- IPPChannelFilter.isLocal(Services.io.newURI(uri)),
- isLocal,
- uri
- );
+ for (const [url, isLocal] of tests) {
+ Assert.equal(IPPChannelFilter.isLocal(makePrincipal(url)), isLocal, url);
}
});
Loading diff…
References
On This Page