Medium firefox UAF 🔧 Commit mapped

Overview

Medium
Severity
CVSS
No
Exploited ITW
Fixed
Fix Status
Impactmoderate
DescriptionUse-after-free in the JavaScript Engine component
ComponentSpiderMonkey
Bug ClassUAF
Tracker2003588
Fix commit0264cf850afd (firefox) +23/-0
CISA KEVNot listed
CreditedGary Kwong and Nan Wang
Disclosed2026-01-13

Files Changed

  • js/src/jit-test/tests/debug/bug-2003588.js
  • js/src/jit-test/tests/debug/bug-2003809.js
  • js/src/proxy/CrossCompartmentWrapper.cpp
diff --git a/js/src/jit-test/tests/debug/bug-2003588.js b/js/src/jit-test/tests/debug/bug-2003588.js
new file mode 100644
index 00000000000..98ecaaeea8b
--- /dev/null
+++ b/js/src/jit-test/tests/debug/bug-2003588.js
@@ -0,0 +1,9 @@
+var x = newGlobal({ newCompartment: true });
+var y = Debugger(x);
+y.x = y;
+y.onDebuggerStatement = function(w) {
+  nukeAllCCWs();
+  w.environment.getVariable("x");
+}
+x.eval('function f(z) { with(z) { debugger } }');
+x.f(y);
diff --git a/js/src/jit-test/tests/debug/bug-2003809.js b/js/src/jit-test/tests/debug/bug-2003809.js
new file mode 100644
index 00000000000..4cb93564bce
--- /dev/null
+++ b/js/src/jit-test/tests/debug/bug-2003809.js
@@ -0,0 +1,8 @@
+var x = newGlobal({ newCompartment: true });
+Debugger(x).onNewScript = function f(z) { m = z };
+x.eval("function g(){}");
+m.setBreakpoint(0, {});
+nukeAllCCWs();
+recomputeWrappers();
+gc();
+
diff --git a/js/src/proxy/CrossCompartmentWrapper.cpp b/js/src/proxy/CrossCompartmentWrapper.cpp
index 1d8013bb008..bf423c332e0 100644
--- a/js/src/proxy/CrossCompartmentWrapper.cpp
+++ b/js/src/proxy/CrossCompartmentWrapper.cpp
@@ -478,6 +478,12 @@ JS_PUBLIC_API bool js::AllowNewWrapper(JS::Compartment* target, JSObject* obj) {
 
   MOZ_ASSERT(obj->compartment() != target);
 
+  // Wrappers for debugger objects are not nuked and we must continue to allow
+  // them to be created or we will break the invariants in Compartment::wrap.
+  if (MOZ_UNLIKELY(obj->is<DebuggerInstanceObject>())) {
+    return true;
+  }
+
   if (target->nukedOutgoingWrappers ||
       obj->nonCCWRealm()->nukedIncomingWrappers) {
     return false;
Loading diff…

Regression Test / PoC

shipped with the fix
diff --git a/js/src/jit-test/tests/debug/bug-2003588.js b/js/src/jit-test/tests/debug/bug-2003588.js
new file mode 100644
index 00000000000..98ecaaeea8b
--- /dev/null
+++ b/js/src/jit-test/tests/debug/bug-2003588.js
@@ -0,0 +1,9 @@
+var x = newGlobal({ newCompartment: true });
+var y = Debugger(x);
+y.x = y;
+y.onDebuggerStatement = function(w) {
+  nukeAllCCWs();
+  w.environment.getVariable("x");
+}
+x.eval('function f(z) { with(z) { debugger } }');
+x.f(y);
diff --git a/js/src/jit-test/tests/debug/bug-2003809.js b/js/src/jit-test/tests/debug/bug-2003809.js
new file mode 100644
index 00000000000..4cb93564bce
--- /dev/null
+++ b/js/src/jit-test/tests/debug/bug-2003809.js
@@ -0,0 +1,8 @@
+var x = newGlobal({ newCompartment: true });
+Debugger(x).onNewScript = function f(z) { m = z };
+x.eval("function g(){}");
+m.setBreakpoint(0, {});
+nukeAllCCWs();
+recomputeWrappers();
+gc();
+
Loading diff…