Moderate firefox Logic Error 🔧 Commit mapped

Overview

Moderate
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Impactmoderate
DescriptionMitigation bypass in the Enterprise Policies component
ComponentCore
Bug ClassLogic Error
Tracker2065646
Fix commit055d8a6648ba (firefox) +39/-3
CISA KEVNot listed
CreditedShu Takahashi
Disclosed2026-09-15

Changed Functions

FunctionChangeNotes
if
browser/components/enterprisepolicies/helpers/WebsiteFilter.sys.mjs
modified
add_task
browser/components/enterprisepolicies/tests/xpcshell/test_websitefilter.js
modified

Files Changed

  • browser/components/enterprisepolicies/helpers/WebsiteFilter.sys.mjs
  • browser/components/enterprisepolicies/tests/browser/browser_policy_websitefilter.js
  • browser/components/enterprisepolicies/tests/xpcshell/test_websitefilter.js
diff --git a/browser/components/enterprisepolicies/helpers/WebsiteFilter.sys.mjs b/browser/components/enterprisepolicies/helpers/WebsiteFilter.sys.mjs
index 8b26f43109b..e733f62d2e3 100644
--- a/browser/components/enterprisepolicies/helpers/WebsiteFilter.sys.mjs
+++ b/browser/components/enterprisepolicies/helpers/WebsiteFilter.sys.mjs
@@ -30,6 +30,10 @@ const PREF_LOGLEVEL = "browser.policies.loglevel";
 
 const lazy = {};
 
+ChromeUtils.defineESModuleGetters(lazy, {
+  ReaderMode: "moz-src:///toolkit/components/reader/ReaderMode.sys.mjs",
+});
+
 ChromeUtils.defineLazyGetter(lazy, "log", () => {
   let { ConsoleAPI } = ChromeUtils.importESModule(
     "resource://gre/modules/Console.sys.mjs"
@@ -116,14 +120,14 @@ export let WebsiteFilter = {
     let url = contentLocation.spec.toLowerCase();
     if (contentLocation.scheme == "view-source") {
       url = contentLocation.pathQueryRef;
-    } else if (url.startsWith("about:reader?url=")) {
-      url = decodeURIComponent(url.substr(17));
+    } else if (url.startsWith("about:reader?")) {
+      url = lazy.ReaderMode.getOriginalUrl(url);
     }
     if (
       contentType == Ci.nsIContentPolicy.TYPE_DOCUMENT ||
       contentType == Ci.nsIContentPolicy.TYPE_SUBDOCUMENT
     ) {
-      if (!this.isAllowed(url)) {
+      if (!url || !this.isAllowed(url)) {
         return Ci.nsIContentPolicy.REJECT_POLICY;
       }
     }
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_websitefilter.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_websitefilter.js
index be51e76dcef..0fa0dd4c809 100644
--- a/browser/components/enterprisepolicies/tests/browser/browser_policy_websitefilter.js
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_websitefilter.js
@@ -42,6 +42,11 @@ add_task(async function test_http() {
     "about:READER?url=" + SUPPORT_FILES_PATH + BLOCKED_PAGE,
     true
   );
+  await checkBlockedPage(
+    "about:reader?e=1&url=" +
+      encodeURIComponent(SUPPORT_FILES_PATH + BLOCKED_PAGE),
+    true
+  );
   await checkBlockedPage(SUPPORT_FILES_PATH + EXCEPTION_PAGE, false);
 
   await checkBlockedPage(SUPPORT_FILES_PATH + "301.sjs", true);
diff --git a/browser/components/enterprisepolicies/tests/xpcshell/test_websitefilter.js b/browser/components/enterprisepolicies/tests/xpcshell/test_websitefilter.js
index 103004c8a82..d862fb33a81 100644
--- a/browser/components/enterprisepolicies/tests/xpcshell/test_websitefilter.js
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_websitefilter.js
@@ -46,3 +46,30 @@ add_task(async function test_host_normalization() {
     "Unparseable URL should be blocked"
   );
 });
+
+add_task(async function test_reader_mode() {
+  function shouldLoadDocument(url) {
+    return WebsiteFilter.shouldLoad(Services.io.newURI(url), {
+      externalContentPolicyType: Ci.nsIContentPolicy.TYPE_DOCUMENT,
+    });
+  }
+
+  const BLOCKED = encodeURIComponent("https://accounts.firefox.com/signin");
+  const ALLOWED = encodeURIComponent("https://example.org/article");
+
+  equal(
+    shouldLoadDocument(`about:reader?e=1&url=${BLOCKED}`),
+    Ci.nsIContentPolicy.REJECT_POLICY,
+    "Blocked article should be found after another query parameter"
+  );
+  equal(
+    shouldLoadDocument(`about:reader?e=1&url=${ALLOWED}`),
+    Ci.nsIContentPolicy.ACCEPT,
+    "Reader Mode URL for an allowed article should not be blocked"
+  );
+  equal(
+    shouldLoadDocument("about:reader?e=1"),
+    Ci.nsIContentPolicy.REJECT_POLICY,
+    "Reader Mode URL without an article should be blocked"
+  );
+});
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_websitefilter.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_websitefilter.js
index be51e76dcef..0fa0dd4c809 100644
--- a/browser/components/enterprisepolicies/tests/browser/browser_policy_websitefilter.js
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_websitefilter.js
@@ -42,6 +42,11 @@ add_task(async function test_http() {
     "about:READER?url=" + SUPPORT_FILES_PATH + BLOCKED_PAGE,
     true
   );
+  await checkBlockedPage(
+    "about:reader?e=1&url=" +
+      encodeURIComponent(SUPPORT_FILES_PATH + BLOCKED_PAGE),
+    true
+  );
   await checkBlockedPage(SUPPORT_FILES_PATH + EXCEPTION_PAGE, false);
 
   await checkBlockedPage(SUPPORT_FILES_PATH + "301.sjs", true);
diff --git a/browser/components/enterprisepolicies/tests/xpcshell/test_websitefilter.js b/browser/components/enterprisepolicies/tests/xpcshell/test_websitefilter.js
index 103004c8a82..d862fb33a81 100644
--- a/browser/components/enterprisepolicies/tests/xpcshell/test_websitefilter.js
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_websitefilter.js
@@ -46,3 +46,30 @@ add_task(async function test_host_normalization() {
     "Unparseable URL should be blocked"
   );
 });
+
+add_task(async function test_reader_mode() {
+  function shouldLoadDocument(url) {
+    return WebsiteFilter.shouldLoad(Services.io.newURI(url), {
+      externalContentPolicyType: Ci.nsIContentPolicy.TYPE_DOCUMENT,
+    });
+  }
+
+  const BLOCKED = encodeURIComponent("https://accounts.firefox.com/signin");
+  const ALLOWED = encodeURIComponent("https://example.org/article");
+
+  equal(
+    shouldLoadDocument(`about:reader?e=1&url=${BLOCKED}`),
+    Ci.nsIContentPolicy.REJECT_POLICY,
+    "Blocked article should be found after another query parameter"
+  );
+  equal(
+    shouldLoadDocument(`about:reader?e=1&url=${ALLOWED}`),
+    Ci.nsIContentPolicy.ACCEPT,
+    "Reader Mode URL for an allowed article should not be blocked"
+  );
+  equal(
+    shouldLoadDocument("about:reader?e=1"),
+    Ci.nsIContentPolicy.REJECT_POLICY,
+    "Reader Mode URL without an article should be blocked"
+  );
+});
Loading diff…