Fix Intl.DateTimeFormat cross-compartment crash and Connection API robustness

OrigDateTimeFormat constructor called inside exportFunction callback failed
in Firefox compartment boundary. Moved construction to content-script-scope
helper. Also added addEventListener/removeEventListener to Connection override
to prevent crashes in real-time apps like Discord.
This commit is contained in:
sal
2026-03-04 22:03:12 -06:00
parent ac76f93fcb
commit 464a570201
3 changed files with 21 additions and 8 deletions

View File

@@ -1,5 +1,10 @@
# Changelog # Changelog
## 0.5.2
- Fixed Discord crash caused by Intl.DateTimeFormat cross-compartment constructor failure
- Fixed Connection API override missing addEventListener (could crash real-time apps)
## 0.5.1 ## 0.5.1
- Fixed Discord and other complex web apps crashing due to DOM dimension noise - Fixed Discord and other complex web apps crashing due to DOM dimension noise

View File

@@ -247,8 +247,12 @@
effectiveType: "4g", effectiveType: "4g",
downlink: 10, downlink: 10,
rtt: 50, rtt: 50,
saveData: false saveData: false,
}, pageWindow); addEventListener: function() {},
removeEventListener: function() {},
dispatchEvent: function() { return true; },
onchange: null
}, pageWindow, { cloneFunctions: true });
}, pageWindow), }, pageWindow),
configurable: true, configurable: true,
enumerable: true enumerable: true
@@ -330,10 +334,11 @@
const OrigDateTimeFormat = window.Intl.DateTimeFormat; const OrigDateTimeFormat = window.Intl.DateTimeFormat;
// Wrap the Intl.DateTimeFormat constructor to inject spoofed timezone // Wrap the Intl.DateTimeFormat constructor to inject spoofed timezone.
// when no explicit timeZone is provided. This ensures resolvedOptions() // The wrapper creates the real instance in the content script scope
// returns the spoofed timezone and all formatting uses it. // (where OrigDateTimeFormat is a valid constructor) then returns it.
const wrappedDTF = exportFunction(function(locales, options) { // Using a helper avoids cross-compartment constructor failures.
function createDateTimeFormat(locales, options) {
let opts; let opts;
if (options) { if (options) {
try { opts = JSON.parse(JSON.stringify(options)); } catch(e) { opts = {}; } try { opts = JSON.parse(JSON.stringify(options)); } catch(e) { opts = {}; }
@@ -341,8 +346,11 @@
opts = {}; opts = {};
} }
if (!opts.timeZone) opts.timeZone = tzName; if (!opts.timeZone) opts.timeZone = tzName;
// Support both `new Intl.DateTimeFormat()` and `Intl.DateTimeFormat()`
return new OrigDateTimeFormat(locales, opts); return new OrigDateTimeFormat(locales, opts);
}
const wrappedDTF = exportFunction(function(locales, options) {
return createDateTimeFormat(locales, options);
}, pageWindow); }, pageWindow);
try { try {

View File

@@ -1,7 +1,7 @@
{ {
"manifest_version": 2, "manifest_version": 2,
"name": "ContainSite", "name": "ContainSite",
"version": "0.5.1", "version": "0.5.2",
"description": "Per-container fingerprint isolation — each container gets its own device identity", "description": "Per-container fingerprint isolation — each container gets its own device identity",
"permissions": [ "permissions": [
"contextualIdentities", "contextualIdentities",