From 464a570201e0ba4b93f5822122bdd354465b7ad0 Mon Sep 17 00:00:00 2001 From: sal Date: Wed, 4 Mar 2026 22:03:12 -0600 Subject: [PATCH] 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. --- CHANGELOG.md | 5 +++++ inject.js | 22 +++++++++++++++------- manifest.json | 2 +- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e495777..b796f60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # 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 - Fixed Discord and other complex web apps crashing due to DOM dimension noise diff --git a/inject.js b/inject.js index e1360e5..9e7396d 100644 --- a/inject.js +++ b/inject.js @@ -247,8 +247,12 @@ effectiveType: "4g", downlink: 10, rtt: 50, - saveData: false - }, pageWindow); + saveData: false, + addEventListener: function() {}, + removeEventListener: function() {}, + dispatchEvent: function() { return true; }, + onchange: null + }, pageWindow, { cloneFunctions: true }); }, pageWindow), configurable: true, enumerable: true @@ -330,10 +334,11 @@ const OrigDateTimeFormat = window.Intl.DateTimeFormat; - // Wrap the Intl.DateTimeFormat constructor to inject spoofed timezone - // when no explicit timeZone is provided. This ensures resolvedOptions() - // returns the spoofed timezone and all formatting uses it. - const wrappedDTF = exportFunction(function(locales, options) { + // Wrap the Intl.DateTimeFormat constructor to inject spoofed timezone. + // The wrapper creates the real instance in the content script scope + // (where OrigDateTimeFormat is a valid constructor) then returns it. + // Using a helper avoids cross-compartment constructor failures. + function createDateTimeFormat(locales, options) { let opts; if (options) { try { opts = JSON.parse(JSON.stringify(options)); } catch(e) { opts = {}; } @@ -341,8 +346,11 @@ opts = {}; } if (!opts.timeZone) opts.timeZone = tzName; - // Support both `new Intl.DateTimeFormat()` and `Intl.DateTimeFormat()` return new OrigDateTimeFormat(locales, opts); + } + + const wrappedDTF = exportFunction(function(locales, options) { + return createDateTimeFormat(locales, options); }, pageWindow); try { diff --git a/manifest.json b/manifest.json index 7bb1e0e..a2049b1 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 2, "name": "ContainSite", - "version": "0.5.1", + "version": "0.5.2", "description": "Per-container fingerprint isolation — each container gets its own device identity", "permissions": [ "contextualIdentities",