Skip to content

Chrome Web Store keeps rejecting extension due to "Including remotely-hosted code in a Manifest V3 item." #1882

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
CarpenterBug opened this issue Apr 7, 2025 · 14 comments

Comments

@CarpenterBug
Copy link

After reading all the documentation and github issues related to the extensions and the Manifest V3, nothing seem to solve and all my attempts to fix it only made it worse.

The extension is open source and code available in my repo: https://github.com/CarpenterBug/atlassian-verification-reload.

Here are the different code versions and respective CWS violations content:

1. Initial code

//background.js
import posthog from './node_modules/posthog-js/dist/module.js';

posthog.init(Config.getEnvVariable('POSTHOG_KEY'), {
     api_host: 'https://eu.i.posthog.com',
     autocapture: false,
     capture_pageview: false,
     capture_pageleave: false,
     capture_dead_clicks: false,
     disable_surveys: true,
     disable_session_recording: true,
     enable_heatmaps: false,
 });

Violation:

Including remotely-hosted code in a Manifest V3 item.
Violating content:

Code snippet: node_modules/posthog-js/dist/array.js: ""var s = () => { if (!a) return i("document not found"); var s = a.createElement("script"); if (s.type = "text/javascript", s.crossOrigin = "anonymous", s.src = t, s.onload = e => i(void 0, e), s.onerror = e => i(e), e.config.prepare_external_dependency_script && (s = e.config.prepare_external_dependency_script(s)), !s) return i("prepare_external_dependency_script returned null"); var r, n = a.querySelectorAll("body > script"); n.length > 0 ? null === (r = n[0].parentNode) || void 0 === r || r.insertBefore(s, n[0]) : a.body.appendChild(s) }; null != a && a.body ? s() : null == a || a.addEventListener("DOMContentLoaded", s)""loadExternalDependency = (e, t, i) => { var s = "/static/".concat(t, ".js") + "?v=".concat(e.version); if ("remote-config" === t && (s = "/array/".concat(e.config.token, "/config.js")), "toolbar" === t) { var r = 3e5, n = Math.floor(Date.now() / r) * r; s = "".concat(s, "&t=").concat(n) } var o = e.requestRouter.endpointFor("assets", s); U(e, o, i) }, _.__PosthogExtensions__.loadSiteApp = (e, t, i) => { var s = e.requestRouter.endpointFor("api", t); U(e, s, i) };""endpointFor(e) { var t = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : ""; if (t && (t = "/" === t[0] ? t : "/".concat(t)), "ui" === e) return this.uiHost + t; if (this.region === uo.CUSTOM) return this.apiHost + t; var i = vo + t; switch (e) { case "assets": return "https://".concat(this.region, "-assets.").concat(i); case "api": return "https://".concat(this.region, ".").concat(i) } }""

2. Second attempt:

//background.js
import posthog from './node_modules/posthog-js/dist/module.no-external.js';

posthog.init(Config.getEnvVariable('POSTHOG_KEY'), {
     api_host: 'https://eu.i.posthog.com',
     disable_external_dependency_loading: true,
     ...
 });

Violation:

Including remotely-hosted code in a Manifest V3 item.
Violating content:
Code snippet: node_modules/posthog-js/dist/array.js: var s = a.createElement("script");

3. Third attempt:

//background.js
import posthog from './node_modules/posthog-js/dist/module.full.no-external.js';

posthog.init(Config.getEnvVariable('POSTHOG_KEY'), {
     api_host: 'https://eu.i.posthog.com',
     disable_external_dependency_loading: true,
     ...
 });

Violation:

Including remotely-hosted code in a Manifest V3 item.
Violating content:

Code snippet: node_modules/posthog-js/dist/recorder.js: " var Mt, At, kt, Rt, Tt = "KGZ1bmN0aW9uKCkgewogICJ1c2Ugc3RyaWN0IjsKICB2YXIgY2hhcnMgPSAiQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrLyI7CiAgdmFyIGxvb2t1cCA9IHR5cGVvZiBVaW50OEFycmF5ID09PSAidW5kZWZpbmVkIiA/IFtdIDogbmV3IFVpbnQ4QXJyYXkoMjU2KTsKICBmb3IgKHZhciBpID0gMDsgaSA8IGNoYXJzLmxlbmd0aDsgaSsrKSB7CiAgICBsb29rdXBbY2hhcnMuY2hhckNvZGVBdChpKV0gPSBpOwogIH0KICB2YXIgZW5jb2RlID0gZnVuY3Rpb24oYXJyYXlidWZmZXIpIHsKICAgIHZhciBieXRlcyA9IG5ldyBVaW50OEFycmF5KGFycmF5YnVmZmVyKSwgaTIsIGxlbiA9IGJ5dGVzLmxlbmd0aCwgYmFzZTY0ID0gIiI7CiAgICBmb3IgKGkyID0gMDsgaTIgPCBsZW47IGkyICs9IDMpIHsKICAgICAgYmFzZTY0ICs9IGNoYXJzW2J5dGVzW2kyXSA+PiAyXTsKICAgICAgYmFzZTY0ICs9IGNoYXJzWyhieXRlc1tpMl0gJiAzKSA8PCA0IHwgYnl0ZXNbaTIgKyAxXSA+PiA0XTsKICAgICAgYmFzZTY0ICs9IGNoYXJzWyhieXRlc1tpMiArIDFdICYgMTUpIDw8IDIgfCBieXRlc1tpMiArIDJdID4+IDZdOwogICAgICBiYXNlNjQgKz0gY2hhcnNbYnl0ZXNbaTIgKyAyXSAmIDYzXTsKICAgIH0KICAgIGlmIChsZW4gJSAzID09PSAyKSB7CiAgICAgIGJhc2U2NCA9IGJhc2U2NC5zdWJzdHJpbmcoMCwgYmFzZTY0Lmxlbmd0aCAtIDEpICsgIj0iOwogICAgfSBlbHNlIGlmIChsZW4gJSAzID09PSAxKSB7CiAgICAgIGJhc2U2NCA9IGJhc2U2NC5zdWJzdHJpbmcoMCwgYmFzZTY0Lmxlbmd0aCAtIDIpICsgIj09IjsKICAgIH0KICAgIHJldHVybiBiYXNlNjQ7CiAgfTsKICBjb25zdCBsYXN0QmxvYk1hcCA9IC8qIEBfX1BVUkVfXyAqLyBuZXcgTWFwKCk7CiAgY29uc3QgdHJhbnNwYXJlbnRCbG9iTWFwID0gLyogQF9fUFVSRV9fICovIG5ldyBNYXAoKTsKICBhc3luYyBmdW5jdGlvbiBnZXRUcmFuc3BhcmVudEJsb2JGb3Iod2lkdGgsIGhlaWdodCwgZGF0YVVSTE9wdGlvbnMpIHsKICAgIGNvbnN0IGlkID0gYCR7d2lkdGh9LSR7aGVpZ2h0fWA7CiAgICBpZiAoIk9mZnNjcmVlbkNhbnZhcyIgaW4gZ2xvYmFsVGhpcykgewogICAgICBpZiAodHJhbnNwYXJlbnRCbG9iTWFwLmhhcyhpZCkpIHJldHVybiB0cmFuc3BhcmVudEJsb2JNYXAuZ2V0KGlkKTsKICAgICAgY29uc3Qgb2Zmc2NyZWVuID0gbmV3IE9mZnNjcmVlbkNhbnZhcyh3aWR0aCwgaGVpZ2h0KTsKICAgICAgb2Zmc2NyZWVuLmdldENvbnRleHQoIjJkIik7CiAgICAgIGNvbnN0IGJsb2IgPSBhd2FpdCBvZmZzY3JlZW4uY29udmVydFRvQmxvYihkYXRhVVJMT3B0aW9ucyk7CiAgICAgIGNvbnN0IGFycmF5QnVmZmVyID0gYXdhaXQgYmxvYi5hcnJheUJ1ZmZlcigpOwogICAgICBjb25zdCBiYXNlNjQgPSBlbmNvZGUoYXJyYXlCdWZmZXIpOwogICAgICB0cmFuc3BhcmVudEJsb2JNYXAuc2V0KGlkLCBiYXNlNjQpOwogICAgICByZXR1cm4gYmFzZTY0OwogICAgfSBlbHNlIHsKICAgICAgcmV0dXJuICIiOwogICAgfQogIH0KICBjb25zdCB3b3JrZXIgPSBzZWxmOwogIHdvcmtlci5vbm1lc3NhZ2UgPSBhc3luYyBmdW5jdGlvbihlKSB7CiAgICBpZiAoIk9mZnNjcmVlbkNhbnZhcyIgaW4gZ2xvYmFsVGhpcykgewogICAgICBjb25zdCB7IGlkLCBiaXRtYXAsIHdpZHRoLCBoZWlnaHQsIGRhdGFVUkxPcHRpb25zIH0gPSBlLmRhdGE7CiAgICAgIGNvbnN0IHRyYW5zcGFyZW50QmFzZTY0ID0gZ2V0VHJhbnNwYXJlbnRCbG9iRm9yKAogICAgICAgIHdpZHRoLAogICAgICAgIGhlaWdodCwKICAgICAgICBkYXRhVVJMT3B0aW9ucwogICAgICApOwogICAgICBjb25zdCBvZmZzY3JlZW4gPSBuZXcgT2Zmc2NyZWVuQ2FudmFzKHdpZHRoLCBoZWlnaHQpOwogICAgICBjb25zdCBjdHggPSBvZmZzY3JlZW4uZ2V0Q29udGV4dCgiMmQiKTsKICAgICAgY3R4LmRyYXdJbWFnZShiaXRtYXAsIDAsIDApOwogICAgICBiaXRtYXAuY2xvc2UoKTsKICAgICAgY29uc3QgYmxvYiA9IGF3YWl0IG9mZnNjcmVlbi5jb252ZXJ0VG9CbG9iKGRhdGFVUkxPcHRpb25zKTsKICAgICAgY29uc3QgdHlwZSA9IGJsb2IudHlwZTsKICAgICAgY29uc3QgYXJyYXlCdWZmZXIgPSBhd2FpdCBibG9iLmFycmF5QnVmZmVyKCk7CiAgICAgIGNvbnN0IGJhc2U2NCA9IGVuY29kZShhcnJheUJ1ZmZlcik7CiAgICAgIGlmICghbGFzdEJsb2JNYXAuaGFzKGlkKSAmJiBhd2FpdCB0cmFuc3BhcmVudEJhc2U2NCA9PT0gYmFzZTY0KSB7CiAgICAgICAgbGFzdEJsb2JNYXAuc2V0KGlkLCBiYXNlNjQpOwogICAgICAgIHJldHVybiB3b3JrZXIucG9zdE1lc3NhZ2UoeyBpZCB9KTsKICAgICAgfQogICAgICBpZiAobGFzdEJsb2JNYXAuZ2V0KGlkKSA9PT0gYmFzZTY0KSByZXR1cm4gd29ya2VyLnBvc3RNZXNzYWdlKHsgaWQgfSk7CiAgICAgIHdvcmtlci5wb3N0TWVzc2FnZSh7CiAgICAgICAgaWQsCiAgICAgICAgdHlwZSwKICAgICAgICBiYXNlNjQsCiAgICAgICAgd2lkdGgsCiAgICAgICAgaGVpZ2h0CiAgICAgIH0pOwogICAgICBsYXN0QmxvYk1hcC5zZXQoaWQsIGJhc2U2NCk7CiAgICB9IGVsc2UgewogICAgICByZXR1cm4gd29ya2VyLnBvc3RNZXNzYWdlKHsgaWQ6IGUuZGF0YS5pZCB9KTsKICAgIH0KICB9Owp9KSgpOwovLyMgc291cmNlTWFwcGluZ1VSTD1pbWFnZS1iaXRtYXAtZGF0YS11cmwtd29ya2VyLUlKcEM3Z19iLmpzLm1hcAo=", Et = "undefined" != typeof window && window.Blob && new Blob([(Mt = Tt, Uint8Array.from(atob(Mt), (e => e.charCodeAt(0))))], { type: "text/javascript;charset=utf-8""
Code snippet: node_modules/posthog-js/dist/array.full.es5.js: " if (!a) return i("document not found"); var s = a.createElement("script"); if (s.type = "text/javascript", s.crossOrigin = "anonymous", s.src = t, s.onload = e => i(void 0, e), s.onerror = e => i(e), e.config.prepare_external_dependency_script && (s = e.config.prepare_external_dependency_script(s)), !s) return i("prepare_external_dependency_script returned null");"

4. Fourth attempt:

//background.js
import posthog from './node_modules/posthog-js/dist/module.no-external.js';
import './node_modules/posthog-js/dist/array.full.no-external.js';
import './node_modules/posthog-js/dist/recorder.js';

posthog.init(Config.getEnvVariable('POSTHOG_KEY'), {
     api_host: 'https://eu.i.posthog.com',
     disable_external_dependency_loading: true,
     ...
 });

Violation:

Including remotely-hosted code in a Manifest V3 item.
Violating content:

Code snippet: node_modules/posthog-js/dist/array.js: j = (e, t, i) => { if (e.config.disable_external_dependency_loading) return H.warn("".concat(t, " was requested but loading of external scripts is disabled.")), i("Loading of external scripts is disabled"); var r = null == a ? void 0 : a.querySelectorAll("script"); if (r) for (var n = 0; n < r.length; n++) if (r[n].src === t) return i(); var s = () => { if (!a) return i("document not found"); var r = a.createElement("script"); if (r.type = "text/javascript", r.crossOrigin = "anonymous", r.src = t, r.onload = e => i(void 0, e), r.onerror = e => i(e), e.config.prepare_external_dependency_script && (r = e.config.prepare_external_dependency_script(r)), !r) return i("prepare_external_dependency_script returned null"); var n, s = a.querySelectorAll("body > script"); s.length > 0 ? null === (n = s[0].parentNode) || void 0 === n || n.insertBefore(r, s[0]) : a.body.appendChild(r) }; null != a && a.body ? s() : null == a || a.addEventListener("DOMContentLoaded", s) }; p.__PosthogExtensions__ = p.__PosthogExtensions__ || {}, p.__PosthogExtensions__.loadExternalDependency = (e, t, i) => { var r = "/static/".concat(t, ".js") + "?v=".concat(e.version); if ("remote-config" === t && (r = "/array/".concat(e.config.token, "/config.js")), "toolbar" === t) { var n = 3e5, s = Math.floor(Date.now() / n) * n; r = "".concat(r, "&t=").concat(s) } var o = e.requestRouter.endpointFor("assets", r); j(e, o, i) }, p.__PosthogExtensions__.loadSiteApp = (e, t, i) => { var r = e.requestRouter.endpointFor("api", t); j(e, r, i) }; class Go { constructor(e) { W(this, "_regionCache", {}), this.instance = e } get apiHost() { var e = this.instance.config.api_host.trim().replace(/\/$/, ""); return "https://app.posthog.com" === e ? "https://us.i.posthog.com" : e } get uiHost() { var e, t = null === (e = this.instance.config.ui_host) || void 0 === e ? void 0 : e.replace(/\/$/, ""); return t || (t = this.apiHost.replace(".".concat(Vo), ".posthog.com")), "https://app.posthog.com" === t ? "https://us.posthog.com" : t } get region() { return this._regionCache[this.apiHost] || (/https:\/\/(app|us|us-assets)(\.i)?\.posthog\.com/i.test(this.apiHost) ? this._regionCache[this.apiHost] = Ho.US : /https:\/\/(eu|eu-assets)(\.i)?\.posthog\.com/i.test(this.apiHost) ? this._regionCache[this.apiHost] = Ho.EU : this._regionCache[this.apiHost] = Ho.CUSTOM), this._regionCache[this.apiHost] } endpointFor(e) { var t = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : ""; if (t && (t = "/" === t[0] ? t : "/".concat(t)), "ui" === e) return this.uiHost + t; if (this.region === Ho.CUSTOM) return this.apiHost + t; var i = Vo + t; switch (e) { case "assets": return "https://".concat(this.region, "-assets.").concat(i); case "api": return "https://".concat(this.region, ".").concat(i) } } }
Code snippet: node_modules/posthog-js/dist/main.js: j = (e, t, i) => { if (e.config.disable_external_dependency_loading) return H.warn("".concat(t, " was requested but loading of external scripts is disabled.")), i("Loading of external scripts is disabled"); var r = null == a ? void 0 : a.querySelectorAll("script"); if (r) for (var n = 0; n < r.length; n++) if (r[n].src === t) return i(); var s = () => { if (!a) return i("document not found"); var r = a.createElement("script"); if (r.type = "text/javascript", r.crossOrigin = "anonymous", r.src = t, r.onload = e => i(void 0, e), r.onerror = e => i(e), e.config.prepare_external_dependency_script && (r = e.config.prepare_external_dependency_script(r)), !r) return i("prepare_external_dependency_script returned null"); var n, s = a.querySelectorAll("body > script"); s.length > 0 ? null === (n = s[0].parentNode) || void 0 === n || n.insertBefore(r, s[0]) : a.body.appendChild(r) }; null != a && a.body ? s() : null == a || a.addEventListener("DOMContentLoaded", s) }; p.__PosthogExtensions__ = p.__PosthogExtensions__ || {}, p.__PosthogExtensions__.loadExternalDependency = (e, t, i) => { var r = "/static/".concat(t, ".js") + "?v=".concat(e.version); if ("remote-config" === t && (r = "/array/".concat(e.config.token, "/config.js")), "toolbar" === t) { var n = 3e5, s = Math.floor(Date.now() / n) * n; r = "".concat(r, "&t=").concat(s) } var o = e.requestRouter.endpointFor("assets", r); j(e, o, i) }, p.__PosthogExtensions__.loadSiteApp = (e, t, i) => { var r = e.requestRouter.endpointFor("api", t); j(e, r, i) }; class Go { constructor(e) { W(this, "_regionCache", {}), this.instance = e } get apiHost() { var e = this.instance.config.api_host.trim().replace(/\/$/, ""); return "https://app.posthog.com" === e ? "https://us.i.posthog.com" : e } get uiHost() { var e, t = null === (e = this.instance.config.ui_host) || void 0 === e ? void 0 : e.replace(/\/$/, ""); return t || (t = this.apiHost.replace(".".concat(Vo), ".posthog.com")), "https://app.posthog.com" === t ? "https://us.posthog.com" : t } get region() { return this._regionCache[this.apiHost] || (/https:\/\/(app|us|us-assets)(\.i)?\.posthog\.com/i.test(this.apiHost) ? this._regionCache[this.apiHost] = Ho.US : /https:\/\/(eu|eu-assets)(\.i)?\.posthog\.com/i.test(this.apiHost) ? this._regionCache[this.apiHost] = Ho.EU : this._regionCache[this.apiHost] = Ho.CUSTOM), this._regionCache[this.apiHost] } endpointFor(e) { var t = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : ""; if (t && (t = "/" === t[0] ? t : "/".concat(t)), "ui" === e) return this.uiHost + t; if (this.region === Ho.CUSTOM) return this.apiHost + t; var i = Vo + t; switch (e) { case "assets": return "https://".concat(this.region, "-assets.").concat(i); case "api": return "https://".concat(this.region, ".").concat(i) } } }
Code snippet: node_modules/posthog-js/dist/module.full.js: j = (e, t, i) => { if (e.config.disable_external_dependency_loading) return H.warn("".concat(t, " was requested but loading of external scripts is disabled.")), i("Loading of external scripts is disabled"); var r = null == a ? void 0 : a.querySelectorAll("script"); if (r) for (var n = 0; n < r.length; n++) if (r[n].src === t) return i(); var s = () => { if (!a) return i("document not found"); var r = a.createElement("script"); if (r.type = "text/javascript", r.crossOrigin = "anonymous", r.src = t, r.onload = e => i(void 0, e), r.onerror = e => i(e), e.config.prepare_external_dependency_script && (r = e.config.prepare_external_dependency_script(r)), !r) return i("prepare_external_dependency_script returned null"); var n, s = a.querySelectorAll("body > script"); s.length > 0 ? null === (n = s[0].parentNode) || void 0 === n || n.insertBefore(r, s[0]) : a.body.appendChild(r) }; null != a && a.body ? s() : null == a || a.addEventListener("DOMContentLoaded", s) }; p.__PosthogExtensions__ = p.__PosthogExtensions__ || {}, p.__PosthogExtensions__.loadExternalDependency = (e, t, i) => { var r = "/static/".concat(t, ".js") + "?v=".concat(e.version); if ("remote-config" === t && (r = "/array/".concat(e.config.token, "/config.js")), "toolbar" === t) { var n = 3e5, s = Math.floor(Date.now() / n) * n; r = "".concat(r, "&t=").concat(s) } var o = e.requestRouter.endpointFor("assets", r); j(e, o, i) }, p.__PosthogExtensions__.loadSiteApp = (e, t, i) => { var r = e.requestRouter.endpointFor("api", t); j(e, r, i) }; class Go { constructor(e) { W(this, "_regionCache", {}), this.instance = e } get apiHost() { var e = this.instance.config.api_host.trim().replace(/\/$/, ""); return "https://app.posthog.com" === e ? "https://us.i.posthog.com" : e } get uiHost() { var e, t = null === (e = this.instance.config.ui_host) || void 0 === e ? void 0 : e.replace(/\/$/, ""); return t || (t = this.apiHost.replace(".".concat(Vo), ".posthog.com")), "https://app.posthog.com" === t ? "https://us.posthog.com" : t } get region() { return this._regionCache[this.apiHost] || (/https:\/\/(app|us|us-assets)(\.i)?\.posthog\.com/i.test(this.apiHost) ? this._regionCache[this.apiHost] = Ho.US : /https:\/\/(eu|eu-assets)(\.i)?\.posthog\.com/i.test(this.apiHost) ? this._regionCache[this.apiHost] = Ho.EU : this._regionCache[this.apiHost] = Ho.CUSTOM), this._regionCache[this.apiHost] } endpointFor(e) { var t = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : ""; if (t && (t = "/" === t[0] ? t : "/".concat(t)), "ui" === e) return this.uiHost + t; if (this.region === Ho.CUSTOM) return this.apiHost + t; var i = Vo + t; switch (e) { case "assets": return "https://".concat(this.region, "-assets.").concat(i); case "api": return "https://".concat(this.region, ".").concat(i) } } }
Code snippet: node_modules/posthog-js/lib/src/entrypoints/external-scripts-loader.js: var loadScript = function(posthog, url, callback) { if (posthog.config.disable_external_dependency_loading) { logger.warn("".concat(url, " was requested but loading of external scripts is disabled.")); return callback('Loading of external scripts is disabled'); } // If we add a script more than once then the browser will parse and execute it // So, even if idempotent we waste parsing and processing time var existingScripts = document === null || document === void 0 ? void 0 : document.querySelectorAll('script'); if (existingScripts) { for (var i = 0; i < existingScripts.length; i++) { if (existingScripts[i].src === url) { // Script already exists, we still call the callback, they have to be idempotent return callback(); } } } var addScript = function() { var _a; if (!document) { return callback('document not found'); } var scriptTag = document.createElement('script'); scriptTag.type = 'text/javascript'; scriptTag.crossOrigin = 'anonymous'; scriptTag.src = url; scriptTag.onload = function(event) { return callback(undefined, event); }; scriptTag.onerror = function(error) { return callback(error); }; if (posthog.config.prepare_external_dependency_script) { scriptTag = posthog.config.prepare_external_dependency_script(scriptTag); } if (!scriptTag) { return callback('prepare_external_dependency_script returned null'); } var scripts = document.querySelectorAll('body > script'); if (scripts.length > 0) { (_a = scripts[0].parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(scriptTag, scripts[0]); } else { // In exceptional situations this call might load before the DOM is fully ready. document.body.appendChild(scriptTag); } }; if (document === null || document === void 0 ? void 0 : document.body) { addScript(); } else { // Inlining this because we don't care about `passive: true` here // and this saves us ~3% of the bundle size // eslint-disable-next-line posthog-js/no-add-event-listener document === null || document === void 0 ? void 0 : document.addEventListener('DOMContentLoaded', addScript); } }; assignableWindow.__PosthogExtensions__ = assignableWindow.__PosthogExtensions__ || {}; assignableWindow.__PosthogExtensions__.loadExternalDependency = function(posthog, kind, callback) { var scriptUrlToLoad = "/static/".concat(kind, ".js") + "?v=".concat(posthog.version); if (kind === 'remote-config') { scriptUrlToLoad = "/array/".concat(posthog.config.token, "/config.js"); } if (kind === 'toolbar') { // toolbar.js is served from the PostHog CDN, this has a TTL of 24 hours. // the toolbar asset includes a rotating "token" that is valid for 5 minutes. var fiveMinutesInMillis = 5 * 60 * 1000; // this ensures that we bust the cache periodically var timestampToNearestFiveMinutes = Math.floor(Date.now() / fiveMinutesInMillis) * fiveMinutesInMillis; scriptUrlToLoad = "".concat(scriptUrlToLoad, "&t=").concat(timestampToNearestFiveMinutes); } var url = posthog.requestRouter.endpointFor('assets', scriptUrlToLoad); loadScript(posthog, url, callback); }; assignableWindow.__PosthogExtensions__.loadSiteApp = function(posthog, url, callback) { var scriptUrl = posthog.requestRouter.endpointFor('api', url); loadScript(posthog, scriptUrl, callback); };
Code snippet: node_modules/posthog-js/dist/external-scripts-loader.js: j = (e, t, i) => { if (e.config.disable_external_dependency_loading) return H.warn("".concat(t, " was requested but loading of external scripts is disabled.")), i("Loading of external scripts is disabled"); var r = null == a ? void 0 : a.querySelectorAll("script"); if (r) for (var n = 0; n < r.length; n++) if (r[n].src === t) return i(); var s = () => { if (!a) return i("document not found"); var r = a.createElement("script"); if (r.type = "text/javascript", r.crossOrigin = "anonymous", r.src = t, r.onload = e => i(void 0, e), r.onerror = e => i(e), e.config.prepare_external_dependency_script && (r = e.config.prepare_external_dependency_script(r)), !r) return i("prepare_external_dependency_script returned null"); var n, s = a.querySelectorAll("body > script"); s.length > 0 ? null === (n = s[0].parentNode) || void 0 === n || n.insertBefore(r, s[0]) : a.body.appendChild(r) }; null != a && a.body ? s() : null == a || a.addEventListener("DOMContentLoaded", s) }; p.__PosthogExtensions__ = p.__PosthogExtensions__ || {}, p.__PosthogExtensions__.loadExternalDependency = (e, t, i) => { var r = "/static/".concat(t, ".js") + "?v=".concat(e.version); if ("remote-config" === t && (r = "/array/".concat(e.config.token, "/config.js")), "toolbar" === t) { var n = 3e5, s = Math.floor(Date.now() / n) * n; r = "".concat(r, "&t=").concat(s) } var o = e.requestRouter.endpointFor("assets", r); j(e, o, i) }, p.__PosthogExtensions__.loadSiteApp = (e, t, i) => { var r = e.requestRouter.endpointFor("api", t); j(e, r, i) }; class Go { constructor(e) { W(this, "_regionCache", {}), this.instance = e } get apiHost() { var e = this.instance.config.api_host.trim().replace(/\/$/, ""); return "https://app.posthog.com" === e ? "https://us.i.posthog.com" : e } get uiHost() { var e, t = null === (e = this.instance.config.ui_host) || void 0 === e ? void 0 : e.replace(/\/$/, ""); return t || (t = this.apiHost.replace(".".concat(Vo), ".posthog.com")), "https://app.posthog.com" === t ? "https://us.posthog.com" : t } get region() { return this._regionCache[this.apiHost] || (/https:\/\/(app|us|us-assets)(\.i)?\.posthog\.com/i.test(this.apiHost) ? this._regionCache[this.apiHost] = Ho.US : /https:\/\/(eu|eu-assets)(\.i)?\.posthog\.com/i.test(this.apiHost) ? this._regionCache[this.apiHost] = Ho.EU : this._regionCache[this.apiHost] = Ho.CUSTOM), this._regionCache[this.apiHost] } endpointFor(e) { var t = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : ""; if (t && (t = "/" === t[0] ? t : "/".concat(t)), "ui" === e) return this.uiHost + t; if (this.region === Ho.CUSTOM) return this.apiHost + t; var i = Vo + t; switch (e) { case "assets": return "https://".concat(this.region, "-assets.").concat(i); case "api": return "https://".concat(this.region, ".").concat(i) } } }

What am I missing?

Thank you in advance.

@CarpenterBug CarpenterBug changed the title Chrome Web Store keeps rejecting my extension due to "Including remotely-hosted code in a Manifest V3 item." Chrome Web Store keeps rejecting extension due to "Including remotely-hosted code in a Manifest V3 item." Apr 7, 2025
@pauldambra
Copy link
Member

hey, there's an open issue with history here #1464

can you test our new build

//background.js
import posthog from './node_modules/posthog-js/dist/module.no-external.js';
import './node_modules/posthog-js/dist/array.full.no-external.js';

// NB IMPORTING THIS NEW BUILD OF THE RECORDER
import './node_modules/posthog-js/dist/posthog-recorder.js';

posthog.init(Config.getEnvVariable('POSTHOG_KEY'), {
     api_host: 'https://eu.i.posthog.com',
     disable_external_dependency_loading: true,
     ...
 });

@pauldambra pauldambra transferred this issue from PostHog/posthog Apr 8, 2025
@CarpenterBug
Copy link
Author

Thank you @pauldambra. I already submit the package with the fix and I share the outcome once it's approved/rejected.

@CarpenterBug
Copy link
Author

Rejected once again 😓

Code

//background.js
import posthog from './node_modules/posthog-js/dist/module.no-external.js';
import './node_modules/posthog-js/dist/array.full.no-external.js';
import './node_modules/posthog-js/dist/posthog-recorder.js';

posthog.init(Config.getEnvVariable('POSTHOG_KEY'), {
    api_host: 'https://eu.i.posthog.com',
    disable_external_dependency_loading: true,
...
});

Violation

Including remotely-hosted code in a Manifest V3 item.
Violating content:

Code snippet: "node_modules/posthog-js/dist/array.full.js": "ld = (e, t, r) => { if (e.config.disable_external_dependency_loading) return ad.warn("".concat(t, " was requested but loading of external scripts is disabled.")), r("Loading of external scripts is disabled"); var n = null == Gr ? void 0 : Gr.querySelectorAll("script"); if (n) for (var i = 0; i < n.length; i++) if (n[i].src === t) return r(); var o = () => { if (!Gr) return r("document not found"); var n = Gr.createElement("script"); if (n.type = "text/javascript", n.crossOrigin = "anonymous", n.src = t, n.onload = e => r(void 0, e), n.onerror = e => r(e), e.config.prepare_external_dependency_script && (n = e.config.prepare_external_dependency_script(n)), !n) return r("prepare_external_dependency_script returned null"); var i, o = Gr.querySelectorAll("body > script"); o.length > 0 ? null === (i = o[0].parentNode) || void 0 === i || i.insertBefore(n, o[0]) : Gr.body.appendChild(n) }; null != Gr && Gr.body ? o() : null == Gr || Gr.addEventListener("DOMContentLoaded", o) }; Qr.__PosthogExtensions__ = Qr.__PosthogExtensions__ || {}, Qr.__PosthogExtensions__.loadExternalDependency = (e, t, r) => { var n = "/static/".concat(t, ".js") + "?v=".concat(e.version); if ("remote-config" === t && (n = "/array/".concat(e.config.token, "/config.js")), "toolbar" === t) { var i = 3e5, o = Math.floor(Date.now() / i) * i;"

Am I missing something? And is it just me or the violation content / selected snippets seem a bit random? It would be great to get feedback from someone from CWS side (e.g. @oliverdunk).

@pauldambra
Copy link
Member

well it's checking array.full.js which does include remote loading code

but if you're grabbing

import posthog from './node_modules/posthog-js/dist/module.no-external.js';
import './node_modules/posthog-js/dist/array.full.no-external.js';
import './node_modules/posthog-js/dist/posthog-recorder.js';

then it shouldn't do - unless one of those is then accidentally pulling in. the other

@CarpenterBug
Copy link
Author

I'm only using those 3 with disable_external_dependency_loading: true in the init so is it a bug in posthog-js?

@pauldambra
Copy link
Member

if the imports cause you to bundle our lazy loading code, even though that code isn't executed by posthog, then chrome rejects it because it includes code that could load other code 🫠

try just

import './node_modules/posthog-js/dist/array.full.no-external.js';
import './node_modules/posthog-js/dist/posthog-recorder.js';

if you can make a minimal reproducible example repo for how your bundling the code then someone here could take a look... it's just hard to guess at what different bundlers/applications might be doing 😅

@pauldambra
Copy link
Member

or just

import posthog from './node_modules/posthog-js/dist/module.no-external.js';
import './node_modules/posthog-js/dist/posthog-recorder.js';

@CarpenterBug
Copy link
Author

CarpenterBug commented Apr 13, 2025

Since I'm only using the main background.js with a small utils.js file, I'm not using any bundle tool. I just create a .zip file of the repo (https://github.com/CarpenterBug/atlassian-verification-reload) and upload it to CWS.
I'll try your last suggestion and share the results.

@CarpenterBug
Copy link
Author

After too many attempts and refactor the repo to include a bundle, the extension was finally accepted with the following imports:

import posthog from 'posthog-js/dist/module.no-external';
import 'posthog-js/dist/array.no-external.js';
import 'posthog-js/dist/posthog-recorder.js';

I hope it helps others facing the same issue.

Thank you @pauldambra for all your support, really appreciate it.

@pauldambra
Copy link
Member

no worries... i really appreciate you taking the time to validate this 🙌

i'll close this issue now (but feel free to re-open or open a new one if other things crop up)

and will update the docs with the new advice

@pauldambra
Copy link
Member

oh! out of interest why import posthog from module and import array no external?

just the combo you ended up on or...?

@CarpenterBug
Copy link
Author

No special reason, I stuck with your suggestions (#1882 (comment)), removed the full since it seems it was part of the problem and didn't remove the array to see if I could have this extension finally approved. If it's not needed, I might removed it in the next version (of the extension).

@NoiseFan
Copy link

So how did it end up?

@CarpenterBug
Copy link
Author

Approved with this solution: #1882 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants