posthog-js icon indicating copy to clipboard operation
posthog-js copied to clipboard

Chrome Manifest v3 extensions may be rejected due to "obfuscated code"

Open pauldambra opened this issue 1 year ago β€’ 32 comments

follow-up to https://github.com/PostHog/posthog-js/issues/1394

that issue is very long already so I want to have a little more space to breathe for what is a separate problem that will have a different solution

see https://github.com/PostHog/posthog-js/issues/1394#issuecomment-2371497392 from @oliverdunk

his comment carried here:

I took a quick look and didn't see this code present anymore, We had a lot of discussion about this internally, which is why your review took longer than normal - apologies for that. In summary: Creating a worker using a blob URL (this is what the base64 string in your rejection email is used for) violates the script-src policy we intend to apply to MV3 extensions. Due to a Chrome bug, this currently works and would only be caught during review. However, we would like to change that in the future. Once that bug is fixed, this would be dead code in violation of our policies. Our usual rule is to still enforce on this code as (while it may be less likely in this case) we have definitely seen code that looks like dead code become active across updates and used maliciously. Given the above, and that understanding this code is quite hard during review, we have decided that this does violate our policies.

see also image from https://github.com/PostHog/posthog-js/issues/1394#issuecomment-2370278219

other context

pauldambra avatar Oct 14 '24 09:10 pauldambra

first step is likely to get updated to latest rrweb so we can be sure we're not chasing shadows https://github.com/PostHog/posthog-js/pull/1276

pauldambra avatar Oct 14 '24 09:10 pauldambra

Sorry if this question has already been asked but will session replay currently work with a chrome extension V3?

jwarder avatar Oct 15 '24 20:10 jwarder

  • Unable to use with Manifest v3 due to remote code executionΒ #1394 (comment)

Unfortunately it will not pass the review by the Chrome Extension team yet check out the discussion here

https://github.com/PostHog/posthog-js/issues/1394#issuecomment-2399245692

ebloom19 avatar Oct 16 '24 03:10 ebloom19

@pauldambra any new updates on the progress of this issue? We really missing having the session recording observability in our chrome extension.

ebloom19 avatar Oct 26 '24 15:10 ebloom19

@pauldambra any new updates on the progress of this issue? We really missing having the session recording observability in our chrome extension.

Same question, I've paused session recording for a couple of weeks and really need it πŸ˜‚ @pauldambra

DophinL avatar Oct 28 '24 02:10 DophinL

the rrweb upgrades took a bunch of attention so we haven't looked at this yet (i'll make the standard reminder that PRs are welcome if other folk have time to look at it - but i appreciate this is fairly deep in the guts of your dependencies dependency πŸ˜…)

it's been logged here already https://github.com/rrweb-io/rrweb/issues/1578 without any engagement :/

pauldambra avatar Oct 28 '24 08:10 pauldambra

pls prioritize

xrzhuang avatar Nov 01 '24 19:11 xrzhuang

ok, pulling on this thread... it might be possible to fix this and avoid needing to remove Canvas recording support

we can test if https://github.com/rrweb-io/rrweb/pull/1448 would remove this obfuscated code from the bundle in posthog's usage of rrweb, and if we see that folk's extensions start to pass google's checks, then we can prompt the rrweb maintainers and get this fixed upstream so everyone benefits

full disclosure to save people following all the links, that is a PostHog PR to rrweb implementing a change from Sentry's fork of rrweb they they offered to contribute https://github.com/rrweb-io/rrweb/issues/1376. in both cases folk were only looking at bundle size since that predates google's changes to the review process.

pauldambra avatar Nov 02 '24 04:11 pauldambra

ok, pulling on this thread... it might be possible to fix this and avoid needing to remove Canvas recording support

we can test if rrweb-io/rrweb#1448 would remove this obfuscated code from the bundle in posthog's usage of rrweb, and if we see that folk's extensions start to pass google's checks, then we can prompt the rrweb maintainers and get this fixed upstream so everyone benefits

full disclosure to save people following all the links, that is a PostHog PR to rrweb implementing a change from Sentry's fork of rrweb they they offered to contribute rrweb-io/rrweb#1376. in both cases folk were only looking at bundle size since that predates google's changes to the review process.

let me know how i can publish this to the google store we can do this right away to test

xrzhuang avatar Nov 04 '24 18:11 xrzhuang

Thanks for looking into this @pauldambra. I'm going to remove posthog recording right now to get things published.

seawatts avatar Nov 07 '24 18:11 seawatts

Yep, unfortunately and super frustratingly that's the only solution at the moment. We really hate that that's the case

pauldambra avatar Nov 07 '24 20:11 pauldambra

We just fixed this upstream with this PR: https://github.com/rrweb-io/rrweb/pull/1568

Specifically this fixes it in the bundling step as long as the DISABLE_WORKER_INLINING=true flag is set (which we only run while building the extension): https://github.com/rrweb-io/rrweb/blob/d09f561073304b2fcbd426576de1f03d46241e55/vite.config.default.ts#L164-L176

Also see the release.yaml for how this is used to release a new version of the extension to the Chrome store.

Juice10 avatar Dec 12 '24 09:12 Juice10

ok, since the rrweb solution is a separate bundle. i think the shortest fix (and since it's confusing for folk to pick the correct items to build to avoid other google chrome store rejections) is for us to make a separate extensions bundle

i'm going to put this on my to-do list but it's going to be next week at the earliest πŸ˜“

pauldambra avatar Jan 14 '25 12:01 pauldambra

Question: why do this as a post-step job in CI, if this could be solved simply by bumping vite to ^6.0.1?

https://github.com/rrweb-io/rrweb/issues/1578#issuecomment-2612855699

ruiconti avatar Jan 24 '25 15:01 ruiconti

interesting comment on the rrweb side... and great research πŸ’–

for posthog why do it as a post step is because we're not building rrweb :)

if this can be fixed upstream then i'm very happy to do no extra work

pauldambra avatar Jan 24 '25 16:01 pauldambra

Is there a solution for this yet? My extension has just been rejected for the same thing after importing: "import posthog from "posthog-js/dist/module.full.no-external";"

M-J-Murray avatar Feb 13 '25 23:02 M-J-Murray

I only need analytics and surveys without external dependencies. Is there a way I can only import these two features and have webpack not include rrweb from session replay?

M-J-Murray avatar Feb 15 '25 15:02 M-J-Murray

I only need analytics and surveys without external dependencies. Is there a way I can only import these two features and have webpack not include rrweb from session replay?

You can import posthog-js/dist/module.no-external and then posthog-js/dist/surveys to get only analytics and surveys

https://posthog.com/docs/libraries/js

isak102 avatar Feb 15 '25 16:02 isak102

@isak102 thank you, I'll give that a go.

M-J-Murray avatar Feb 15 '25 16:02 M-J-Murray

@isak102 this solution worked for me, thank you πŸ‘

M-J-Murray avatar Feb 27 '25 17:02 M-J-Murray

we've been testing an internal build of rrweb (the recorder tool) that I believe will no longer trigger this warning - but we don't have a chrome extension to test with

if anyone is willing to bundle posthog-recorder instead of recorder in their extension to test that would be amazing!

pauldambra avatar Apr 04 '25 09:04 pauldambra

so instead of

import "posthog-js/dist/recorder.js"

you would

import "posthog-js/dist/posthog-recorder.js"

pauldambra avatar Apr 04 '25 09:04 pauldambra

welcome to email paul AT posthog DOT com or let me know here

pauldambra avatar Apr 04 '25 09:04 pauldambra

@oliverdunk is someone at google able to validate the posthog-recorder.js I think it won't trigger the obfuscated code 🀞

pauldambra avatar Apr 08 '25 17:04 pauldambra

@pauldambra thanks and good to hear that. i will pack my chrome extension dmooji today and ship it with posthog-recorder.js, but it will take 1-3 days for reviewing. can you please share more instruction about how to implement posthog-recorder.js?

Before, I import posthog like this below to prevent remote code warning.

import posthog from "posthog-js/dist/module.full.no-external";

if (process.env.PLASMO_PUBLIC_POSTHOG_API_KEY) {
  try {
    posthog.init(process.env.PLASMO_PUBLIC_POSTHOG_API_KEY, {
      api_host: "https://app.posthog.com",
      persistence: "localStorage",
      autocapture: true,
      person_profiles: "always",
      disable_session_recording: false,
      capture_pageview: true,
      loaded: (posthog) => {
        posthog.register({
          full_url: window.location.href,
          domain: window.location.hostname,
        });
      },
    });
  } catch (err) {
    log.error(err);
  }
}

giftedunicorn avatar Apr 10 '25 02:04 giftedunicorn

hey @giftedunicorn it'll be easier once we know we can ship this internal build of the recorder for now the "full" package already includes the external build of the recorder that triggers the error

so it would look (something) like

// no external so we don't trigger the external code loading static analysis
import posthog from './node_modules/posthog-js/dist/module.no-external.js';
// not the "full" package so that we can choose which recorder
import './node_modules/posthog-js/dist/array.no-external.js';

// NB IMPORTING THIS NEW BUILD OF THE RECORDER
import './node_modules/posthog-js/dist/posthog-recorder.js';
// and then any other extensions you want to add like error tracking or surveys

pauldambra avatar Apr 10 '25 09:04 pauldambra

hey @pauldambra

what about if we are using the "posthog-js/react" lib as follows:

import { PostHogProvider } from "posthog-js/react"; import './node_modules/posthog-js/dist/posthog-recorder.js';

<PostHogProvider apiKey={import.meta.env.VITE_PUBLIC_POSTHOG_KEY} options={{ api_host: import.meta.env.VITE_PUBLIC_POSTHOG_HOST, persistence: "localStorage", disable_external_dependency_loading: true, capture_pageview: true, disable_session_recording: false, }} >

How could I integrate the posthog-recorder in this setup?

ebloom19 avatar Apr 11 '25 02:04 ebloom19

hey @giftedunicorn it'll be easier once we know we can ship this internal build of the recorder for now the "full" package already includes the external build of the recorder that triggers the error

so it would look (something) like

// no external so we don't trigger the external code loading static analysis
import posthog from './node_modules/posthog-js/dist/module.no-external.js';
// not the "full" package so that we can choose which recorder
import './node_modules/posthog-js/dist/array.no-external.js';

// NB IMPORTING THIS NEW BUILD OF THE RECORDER
import './node_modules/posthog-js/dist/posthog-recorder.js';
// and then any other extensions you want to add like error tracking or surveys

I can confirm now the posthog-recorder.js passed the google extension reviewing and no more obfuscated code warning any more.

giftedunicorn avatar Apr 13 '25 08:04 giftedunicorn

I can also confirm our chrome extension successfully passed and is receiving session recordings successfully πŸŽ‰ πŸ™Œ

ebloom19 avatar Apr 13 '25 13:04 ebloom19

That's amazing news! Thanks for testing and confirming πŸ™Œ

Will finalise the rollout to switch to this bundle

pauldambra avatar Apr 22 '25 11:04 pauldambra