Low firefox Logic Error 🔧 Commit mapped

Overview

Low
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
Impactlow
DescriptionDenial-of-service in the DOM: Service Workers component
ComponentDOM
Bug ClassLogic Error
Tracker1999084
Fix commite784d5c2e5c5 (firefox) +22/-0
CISA KEVNot listed
CreditedElysee Franchuk, Caleb Lerch
Disclosed2026-01-13

Changed Functions

FunctionChangeNotes
nsPIDOMWindowInner
dom/workers/WorkerCommon.h
modified
if
dom/workers/loader/NetworkLoadHandler.cpp
modified

Files Changed

  • dom/locales/en-US/chrome/dom/dom.properties
  • dom/serviceworkers/ServiceWorkerScriptCache.cpp
  • dom/workers/WorkerCommon.h
  • dom/workers/loader/NetworkLoadHandler.cpp
diff --git a/dom/locales/en-US/chrome/dom/dom.properties b/dom/locales/en-US/chrome/dom/dom.properties
index a0b4c416545..dc6bcef615f 100644
--- a/dom/locales/en-US/chrome/dom/dom.properties
+++ b/dom/locales/en-US/chrome/dom/dom.properties
@@ -179,6 +179,7 @@ HittingMaxWorkersPerDomain2=A Worker could not be started immediately because ot
 # LOCALIZATION NOTE: Do not translate "Application Cache API", "AppCache" and "ServiceWorker".
 AppCacheWarning=The Application Cache API (AppCache) is deprecated and will be removed at a future date.  Please consider using ServiceWorker for offline support.
 # LOCALIZATION NOTE: Do not translate "Worker".
+WorkerScriptTooLargeError=The worker script is too large and cannot be loaded.
 EmptyWorkerSourceWarning=Attempting to create a Worker from an empty source. This is probably unintentional.
 NavigatorGetUserMediaWarning=navigator.mozGetUserMedia has been replaced by navigator.mediaDevices.getUserMedia
 # LOCALIZATION NOTE: Do not translate "RTCPeerConnection", "getLocalStreams", "getRemoteStreams", "getSenders" or "getReceivers".
diff --git a/dom/serviceworkers/ServiceWorkerScriptCache.cpp b/dom/serviceworkers/ServiceWorkerScriptCache.cpp
index 52fc41913bb..cce12b8e0a9 100644
--- a/dom/serviceworkers/ServiceWorkerScriptCache.cpp
+++ b/dom/serviceworkers/ServiceWorkerScriptCache.cpp
@@ -894,6 +894,12 @@ CompareNetwork::OnStreamComplete(nsIStreamLoader* aLoader,
   nsresult rv = NS_ERROR_FAILURE;
   auto guard = MakeScopeExit([&] { NetworkFinish(rv); });
 
+  if (aLen > GetWorkerScriptMaxSizeInBytes()) {
+    rv = NS_ERROR_DOM_ABORT_ERR;  // This will make sure an exception gets
+                                  // thrown to the global.
+    return NS_OK;
+  }
+
   if (NS_WARN_IF(NS_FAILED(aStatus))) {
     rv = (aStatus == NS_ERROR_REDIRECT_LOOP) ? NS_ERROR_DOM_SECURITY_ERR
                                              : aStatus;
diff --git a/dom/workers/WorkerCommon.h b/dom/workers/WorkerCommon.h
index af8d36c0d72..5c4ffec4f39 100644
--- a/dom/workers/WorkerCommon.h
+++ b/dom/workers/WorkerCommon.h
@@ -8,6 +8,7 @@
 #define mozilla_dom_workers_WorkerCommon_h
 
 #include "js/TypeDecls.h"
+#include "nsString.h"
 
 class nsPIDOMWindowInner;
 
@@ -61,6 +62,11 @@ bool IsWorkerDebuggerSandbox(JSObject* object);
 void UpdateWorkersPlaybackState(const nsPIDOMWindowInner& aWindow,
                                 bool aIsPlayingAudio);
 
+inline size_t GetWorkerScriptMaxSizeInBytes() {
+  // This is the max size that any of our worker scripts can be.
+  return nsString::LengthStorage::kMax;
+}
+
 }  // namespace mozilla::dom
 
 #endif  // mozilla_dom_workers_WorkerCommon_h
diff --git a/dom/workers/loader/NetworkLoadHandler.cpp b/dom/workers/loader/NetworkLoadHandler.cpp
index 0a675fb68f8..a8ef8ff1f04 100644
--- a/dom/workers/loader/NetworkLoadHandler.cpp
+++ b/dom/workers/loader/NetworkLoadHandler.cpp
@@ -68,6 +68,15 @@ nsresult NetworkLoadHandler::DataReceivedFromNetwork(nsIStreamLoader* aLoader,
                                                      const uint8_t* aString) {
   AssertIsOnMainThread();
   MOZ_ASSERT(!mRequestHandle->IsEmpty());
+
+  if (aStringLen > GetWorkerScriptMaxSizeInBytes()) {
+    Document* parentDoc = mWorkerRef->Private()->GetDocument();
+    nsContentUtils::ReportToConsole(nsIScriptError::errorFlag, "DOM"_ns,
+                                    parentDoc, nsContentUtils::eDOM_PROPERTIES,
+                                    "WorkerScriptTooLargeError");
+    return NS_ERROR_DOM_ABORT_ERR;
+  }
+
   WorkerLoadContext* loadContext = mRequestHandle->GetContext();
 
   if (!loadContext->mChannel) {
Loading diff…