From d56c179ddbf738ace80659a7805aef4268e6d309 Mon Sep 17 00:00:00 2001 From: martgil <46025304+martgil@users.noreply.github.com> Date: Tue, 4 Aug 2026 14:28:59 +0800 Subject: [PATCH] fix: firefox content script sandbox bug --- extension/lib/streams-firefox-fix.js | 23 +++++++++++++++++++++++ package-lock.json | 4 ++-- package.json | 3 ++- scripts/build.js | 3 +++ tooling/build-types-and-manifests.ts | 9 +++++++++ 5 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 extension/lib/streams-firefox-fix.js diff --git a/extension/lib/streams-firefox-fix.js b/extension/lib/streams-firefox-fix.js new file mode 100644 index 00000000000..f0719faf980 --- /dev/null +++ b/extension/lib/streams-firefox-fix.js @@ -0,0 +1,23 @@ +// ©️ 2016 - present FlowCrypt a.s. Limitations apply. Contact human@flowcrypt.com +// Firefox content-script sandbox workaround. +// +// In the Firefox content-script isolated world, `ReadableStream`/`TransformStream` are Xray +// wrappers of the page's native implementations. Constructing them with a source object from +// the sandbox realm throws `Permission denied to access property "autoAllocateChunkSize"` +// (https://bugzilla.mozilla.org/show_bug.cgi?id=1757836), which broke openpgp.js's compressed +// packet (zip/zlib) decompression with `MalformedPacketError: Parsing CompressedDataPacket failed`. +// +// This script must run BEFORE the web-streams-polyfill script (both loaded before /lib/openpgp.js): +// 1. It hides the native CompressionStream/DecompressionStream globals so that openpgp.js +// (loaded next) selects its bundled fflate JS fallback instead of +// `stream.pipeThrough(native DecompressionStream)`, which fails the web-streams-polyfill's +// brand checks. +// 2. The web-streams-polyfill script then installs its own same-realm ReadableStream/ +// WritableStream/TransformStream implementations on the sandbox global, so all stream objects +// created by openpgp.js and web-stream-tools live in a single realm and work as expected. +if (typeof globalThis.CompressionStream !== 'undefined') { + globalThis.CompressionStream = undefined; +} +if (typeof globalThis.DecompressionStream !== 'undefined') { + globalThis.DecompressionStream = undefined; +} diff --git a/package-lock.json b/package-lock.json index 50cd099eda3..5210dce8040 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,7 +22,8 @@ "linkifyjs": "4.3.3", "node-forge": "1.4.0", "squire-rte": "2.4.8", - "sweetalert2": "11.26.25" + "sweetalert2": "11.26.25", + "web-streams-polyfill": "3.3.3" }, "devDependencies": { "@openpgp/web-stream-tools": "0.3.1", @@ -10757,7 +10758,6 @@ "version": "3.3.3", "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", - "dev": true, "license": "MIT", "engines": { "node": ">= 8" diff --git a/package.json b/package.json index 2f12a4db83d..29749f05840 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,8 @@ "linkifyjs": "4.3.3", "node-forge": "1.4.0", "squire-rte": "2.4.8", - "sweetalert2": "11.26.25" + "sweetalert2": "11.26.25", + "web-streams-polyfill": "3.3.3" }, "scripts": { "build": "npm run symlink-core && node ./scripts/build.js", diff --git a/scripts/build.js b/scripts/build.js index b6c93afa96c..8650698e89e 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -67,6 +67,9 @@ const copyDependencies = async () => { // Reference: https://github.com/mozilla/pdf.js/issues/18006#issuecomment-2078739672 ['pdfjs-dist/legacy/build/pdf.min.mjs', 'lib/pdf.min.mjs'], ['pdfjs-dist/legacy/build/pdf.worker.min.mjs', 'lib/pdf.worker.min.mjs'], + // polyfill Web Streams in the Firefox content-script sandbox, see + // https://bugzilla.mozilla.org/show_bug.cgi?id=1757836 + ['web-streams-polyfill/dist/polyfill.min.js', 'lib/web-streams-polyfill.min.js'], ['bootstrap/dist/js/bootstrap.min.js', 'lib/bootstrap/bootstrap.min.js'], ['bootstrap/dist/css/bootstrap.min.css', 'lib/bootstrap/bootstrap.min.css'], ]; diff --git a/tooling/build-types-and-manifests.ts b/tooling/build-types-and-manifests.ts index 97054225ffa..1b4fb53f540 100644 --- a/tooling/build-types-and-manifests.ts +++ b/tooling/build-types-and-manifests.ts @@ -36,6 +36,15 @@ addManifest('firefox-consumer', manifest => { strict_min_version: '112.0', // eslint-disable-line @typescript-eslint/naming-convention }, }; + // Web Streams are broken in the Firefox content-script sandbox (Permission denied to access + // property "autoAllocateChunkSize" - https://bugzilla.mozilla.org/show_bug.cgi?id=1757836). + // Load the streams-fix shim + web-streams-polyfill BEFORE openpgp.js, so that stream objects + // created by openpgp.js / web-stream-tools live in a single (sandbox) realm. + // This is only needed in the content script: extension pages and the service worker are + // privileged and keep using the native implementations. + for (const csDef of manifest.content_scripts ?? []) { + csDef.js = ['/lib/streams-firefox-fix.js', '/lib/web-streams-polyfill.min.js', ...(csDef.js ?? [])]; + } manifest.background = { type: 'module', scripts: ['/js/service_worker/background.js'],