Skip to content
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

Chrome Web Store Team complains a Violation: My Extension (Cancelly.ca) is injecting the enterprise.js externally from the Google API in the src/index.js file. #7617

Closed
umrashrf opened this issue Sep 8, 2023 · 105 comments

Comments

@umrashrf
Copy link

umrashrf commented Sep 8, 2023

Operating System

macOS Ventura 13.5

Browser Version

116.0.5845.179 (Official Build) (arm64)

Firebase SDK Version

^10.1.0

Firebase SDK Product:

Auth

Describe your project's tooling

I am using this https://github.com/JohnBra/vite-web-extension

Describe the problem

Following code after the build generates minified files containing URLs with enterprise.js so the Chrome Web Store Team complains of a violation.

import firebaseConfig from './firebase_config';
import { initializeApp } from 'firebase/app';
import { getAuth, signInWithCustomToken, signOut } from 'firebase/auth';

const app = initializeApp(firebaseConfig);
const auth = getAuth(app);

Steps and code to reproduce issue

Defined in the problem.

@umrashrf umrashrf added new A new issue that hasn't be categoirzed as question, bug or feature request question labels Sep 8, 2023
@jbalidiong jbalidiong added needs-attention and removed new A new issue that hasn't be categoirzed as question, bug or feature request labels Sep 8, 2023
@NhienLam
Copy link
Contributor

Hi @umrashrf, the enterprise.js is for reCAPTCHA enterprise. The script will only load if you use reCAPTCHA enterprise. Can you give more information about the violation?

We also have reCAPTCHA v2 script in

const RECAPTCHA_BASE = 'https://www.google.com/recaptcha/api.js?';
, does this cause an issue too?

They have been there for a long time already.

@meetyan
Copy link

meetyan commented Sep 12, 2023

@NhienLam

I have a similar complaint from Google saying that my extension violates the program policy.

Violation reference ID: Blue Argon

Violation: Including remotely hosted code in a Manifest V3 item.

After some investigation, it seems that there's a _loadJS function that creates a script tag and loads code from a remote URL.

https://github.com/firebase/firebase-js-sdk/blob/98cfcbd0c0629d4aee60f686edc0da3e27ce36c6/packages/auth/src/platform_browser/load_js.ts#L25C1-L40C2

Then in gapi.ts, the function is called to load from an external API (which is the Google API).

https://github.com/firebase/firebase-js-sdk/blob/98cfcbd0c0629d4aee60f686edc0da3e27ce36c6/packages/auth/src/platform_browser/iframe/gapi.ts#L89C1-L108C32

Could you please have a look and help us do something to solve the issue?

Thank you.

@carl-jin
Copy link

I also received a rejection notification today. Several of my extensions rely on Firebase's auth, and now they can't be updated.

@hsubox76
Copy link
Contributor

I think this is related to the push to Manifest V3 which will be required of all Chrome web store apps as of Jan 2024. Specifically this prohibition against remotely hosted files: https://developer.chrome.com/docs/extensions/mv3/intro/mv3-overview/#remotely-hosted-code

@meetyan
Copy link

meetyan commented Sep 13, 2023

The Chrome Web Store team has officially confirmed that the error is caused by the _loadJS function responsible for loading the Google API.

Here's what they say:

We would like to let you know that under static/js/background.js and static/js/content-script.js files there is an external js file (https://apis.google.com/js/api.js?onload=${t}) that was injected which is against our Chrome Web Store policies.

Please remove the external code file(js file) or else include that external js file in the extension’s code package and re-submit your extension for a review. Your submission will be approved if we find it to be compliant with all our policies.

Looks like something has to change to solve this issue.

@umrashrf
Copy link
Author

I will add, it looks like that enterprise.js is needed for reCaptcha as part of the signInWithPhoneNumber function. In my app, I am not using that function or that way of signing in at all. The problem is that all sign-in functions are in the same file/class in the firebase sdk.

@umrashrf
Copy link
Author

umrashrf commented Sep 18, 2023

enterprise

@NhienLam I am not using enterprise. I am using npm install firebase and that's it.

@prameshj
Copy link
Contributor

prameshj commented Sep 18, 2023

I see there is some discussion about it in this email thread as well

Can folks try if the solution posted in that thread works? That thread shows the implementation with the non-modular SDK which is not tree-shakeable. With the modular SDK, the recaptcha script loader could get tree-shaken if unused.

Can you try something like this:

import { GoogleAuthProvider, initializeAuth } from "firebase/auth";

chrome.identity.getAuthToken({ 'interactive': true }, async (token) => {
    const credential = GoogleAuthProvider.credential(null, token);
      try {
        const app = initializeApp({/** Your app config */});
        const auth = initializeAuth(app, {popupRedirectResolver: undefined, persistence: indexDBLocalPersistence});
        const {user} = await auth.signInWithCredential(credential)
        console.log(`the user object is here! - ${user}`)
      } catch (e) {
        console.error(error);
      }
}); 

Please use SDK version 9.19.0 or older.

@prameshj
Copy link
Contributor

Also, in addition, can folks answer the following questions: 1) Are you using the modular or compat SDK? 2) Which auth methods are you using in the extension code? Thanks!

@umrashrf
Copy link
Author

@prameshj My extensions package.json contains type: "module"

package.json

"dependencies": {
    "firebase": "^10.1.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "vite-plugin-css-injected-by-js": "^3.1.1",
    "webextension-polyfill": "^0.10.0"
  },
$ grep -E 'node_modules/.*compat.*' package-lock.json 
    "node_modules/@babel/compat-data": {
    "node_modules/@firebase/analytics-compat": {
    "node_modules/@firebase/analytics-compat/node_modules/tslib": {
    "node_modules/@firebase/app-check-compat": {
    "node_modules/@firebase/app-check-compat/node_modules/tslib": {
    "node_modules/@firebase/app-compat": {
    "node_modules/@firebase/app-compat/node_modules/tslib": {
    "node_modules/@firebase/auth-compat": {
    "node_modules/@firebase/auth-compat/node_modules/tslib": {
    "node_modules/@firebase/database-compat": {
    "node_modules/@firebase/database-compat/node_modules/tslib": {
    "node_modules/@firebase/firestore-compat": {
    "node_modules/@firebase/firestore-compat/node_modules/tslib": {
    "node_modules/@firebase/functions-compat": {
    "node_modules/@firebase/functions-compat/node_modules/tslib": {
    "node_modules/@firebase/installations-compat": {
    "node_modules/@firebase/installations-compat/node_modules/tslib": {
    "node_modules/@firebase/messaging-compat": {
    "node_modules/@firebase/messaging-compat/node_modules/tslib": {
    "node_modules/@firebase/performance-compat": {
    "node_modules/@firebase/performance-compat/node_modules/tslib": {
    "node_modules/@firebase/remote-config-compat": {
    "node_modules/@firebase/remote-config-compat/node_modules/tslib": {
    "node_modules/@firebase/storage-compat": {
    "node_modules/@firebase/storage-compat/node_modules/tslib": {
    "node_modules/core-js-compat": {
@prameshj
Copy link
Contributor

Thanks.. it would be great if folks can confirm:

  1. if the workaround above helps?
  2. What auth providers are you using in extensions?
  3. Are you using the modular web SDK?
@leonidkuznetsov18
Copy link

We encountered a similar issue. According to the requirements outlined by the Google Chrome Extension team (found at https://developer.chrome.com/docs/webstore/program-policies/mv3-requirements/), we are prohibited from utilizing files hosted on a third-party server or CDN. All files must be stored locally. Could you please create a version where these files are stored locally?

Here are the links to the images we need to use:
image
image

@khlevon
Copy link

khlevon commented Sep 25, 2023

I have a similar issue and tried the workaround suggested by @prameshj, but it did not work. To temporarily solve the problem, I added post build script to replace _loadJS function content with an empty promise. It can cover most cases, but in some cases, the logic can be breached. As I use vite with rollup, I configure the post-build script in this way (you can use this regex to implement your own post-build script):

import modify from 'rollup-plugin-modify';

//...

rollupOptions: {
    plugins: [
        modify({
            find: /function\s*\w*\s*_loadJS\([\w\s,]*\)\s*{([\w\W]*?)}$/gim,
            replace: 'function _loadJS() { return Promise.resolve(); };',
        }),
     ]
}
@Georg7
Copy link

Georg7 commented Sep 25, 2023

Same issue here.

Also, in addition, can folks answer the following questions: 1) Are you using the modular or compat SDK? 2) Which auth methods are you using in the extension code? Thanks!

  1. Using modular SDK
  2. getAuth, onAuthStateChanged, signInWithCustomToken, signOut, signInWithCredential, getAdditionalUserInfo

Workaround doesn't help. We don't use chrome.identity.getAuthToken.; instead authenticating the user on our website, creating/sending custom token to the extension where we authenticate the user then with signInWithCustomToken.

@XchHarutyunyan
Copy link

XchHarutyunyan commented Sep 25, 2023

I have the same problem, I tried a lot. I have implemented Google Authentication via the popup, but again I get "Breach Link ID: Blue Argon".
Code for Google auth.

auth.ts

import {
  GoogleAuthProvider,
  OAuthCredential,
  signInWithCredential,
} from "firebase/auth";
import { storage } from "webextension-polyfill";

const getGoogleAccessToken = async (prompt?: boolean): Promise<string> => {
  const { accessToken } = await storage.local.get("accessToken");

  if (accessToken) {
    return accessToken;
  }

  if (prompt === false) return "";
  return new Promise((resolve) => {
    chrome.identity.getAuthToken({ interactive: true }, token =>
    {
      if (chrome.runtime.lastError || ! token) {
        console.log(chrome.runtime.lastError);
        return
      }
      resolve(token);
    })
  });
};

const getGoogleAuthCredential = async (
  prompt?: boolean
): Promise<OAuthCredential | null> => {
  const accessToken = await getGoogleAccessToken(prompt);
  await storage.local.set({ accessToken });
  const credential = GoogleAuthProvider.credential(null, accessToken);

  return credential;
};

const logIn = async (prompt?: boolean) => {
  try {
    const credential = await getGoogleAuthCredential(prompt);
    const result = await signInWithCredential(auth, credential);
    return result.user;
  } catch (e) {
    console.error(e);
    storage.local.remove("accessToken");
    return null;
  }
};

manifest.json

"background": {
    "service_worker": "auth.ts",
    "type": "module"
  },
  "permissions": ["storage", "tabs", "identity"],
  "content_security_policy": {
    "extension_pages": "script-src 'self'; object-src 'self'; script-src-elem 'self' 'unsafe-inline';"
  },
  "oauth2": {
    "client_id": "CLIENT_ID",
    "scopes": [
      "https://www.googleapis.com/auth/userinfo.profile",
      "https://www.googleapis.com/auth/userinfo.email"
    ]
  },
@patrickkettner
Copy link

@Shajeel-Afzal the issue with your latest submission is the same as my last update - your code is trying to use remote code. Look for "apis.google.com" in the generated build to see what I mean

@Shajeel-Afzal
Copy link

@patrickkettner unfortunately our Chrome Extension is taken down because of this issue in the library. I removed the enterprise.js file and other files that were mentioned by @XchHarutyunyan!

I also added the patch npm that was required but that also did not work.

I also tried looking into the loadJS calls in the build there were not any.

Is it possible to get the same extension back after getting this problem fixed or do we have to upload a new extension?

Please help!

@patrickkettner
Copy link

@Shajeel-Afzal I understand. I would love to help. I am telling you exactly what to do. Generate a build of your extension, then search the output for the string "apis.google.com". If you see it, there is still a problem. To get you unblocked asap, removing the URL from the build should take care of it.

@Shajeel-Afzal
Copy link

Thank you @patrickkettner!

apis.google.com is present in the manifest.json file before generating the build:
image

This is what I am doing after generating the build using the commaind: yarn build:chrome

1- I remove the chrome folder
image

2- Unarchive the chrome.zip folder & open it in VS Code.
3- I see that it is found in the these places in the generated build:
image

I believe you want me to delete it from background.bundle.js and contentScript.bundle.js file?

@patrickkettner
Copy link

patrickkettner commented Nov 4, 2023 via email

@Shajeel-Afzal
Copy link

@patrickkettner so I need to remove it from the manifest as well?

@Shajeel-Afzal
Copy link

@patrickkettner I need to delete this part only, right?
image

@patrickkettner
Copy link

@Shajeel-Afzal I think you should email me moving forward to avoid a lot of noise to this issue, since a lot of people are following it. My email is patrickkettner@google.com.

so I need to remove it from the manifest as well?

JSON is not javascript, but it is not doing anything in your manifest.json so oyu may as well remove it.

I need to delete this part only, right?

No, you need to remove the entire URL.

@XchHarutyunyan
Copy link

@XchHarutyunyan I just sent you a message on LinkedIn! Can you please reply so that we can solve this problem?

Thanks.

I replied to your message

@rendomnet
Copy link

what is the solution for project build with Vite?

@patrickkettner
Copy link

patrickkettner commented Nov 9, 2023 via email

@google-oss-bot
Copy link
Contributor

Hey @umrashrf. We need more information to resolve this issue but there hasn't been an update in 5 weekdays. I'm marking the issue as stale and if there are no new updates in the next 5 days I will close it automatically.

If you have more information that will help us get to the bottom of this, just add a comment!

@spookyuser
Copy link

If you want to quickly scan a folder for the links that seem to be triggering this before uploading to the chrome webstore I made a cli here https://github.com/spookyuser/badlinks basically:

  • npx badlinks <folder> to scan
  • npx badlinks <folder> -r to remove

I'm just using this as a sanity check because I thought I had removed them a few times and they kept coming back

@wadhia-yash
Copy link

@spookyuser how to install and use this cli?

@spookyuser
Copy link

@spookyuser how to install and use this cli?

You can do npm install -g badlinks then badlinks <folder>

Or if you have a recent version of npm you can probably just do it in one shot with npx, so npx badlinks <folder>

@wadhia-yash
Copy link

wadhia-yash commented Nov 21, 2023

@spookyuser
I tried using the above command but doesn't work.
Maybe I have missed something.
I am attaching the screenshot if I have missed something please guide me.

Screenshot 2023-11-21 at 5 43 31 PM
@umrashrf umrashrf changed the title Chrome Web Store Team complains a Violation: Extension is injecting the enterprise.js externally from the Google API in the src/index.js file. Nov 21, 2023
@spookyuser
Copy link

spookyuser commented Nov 21, 2023

@spookyuser I tried using the above command but doesn't work. Maybe I have missed something. I am attaching the screenshot if I have missed something please guide me.

Screenshot 2023-11-21 at 5 43 31 PM

Oops sorry i published it incorrectly, should be working now, if you do npx badlinks <folder> or npx badlinks -h

oh and npm install -g should also work if you prefer it!

If it doesn't work or does work let me know here: https://github.com/spookyuser/badlinks/discussions <3

@ESUITDEV
Copy link

Guys, CWS now considers the compressed Firebase SDK code to be 'obfuscated.' My two extensions have already received a 'rejected' notification (they took 2-3 working days for the review).

Screenshot 2023-12-15 at 8 10 20 AM Screenshot 2023-12-15 at 8 15 32 AM
@hsubox76
Copy link
Contributor

hsubox76 commented Jan 25, 2024

We are fixing this (the script injection issue) in the next release with a separate auth import: #7766

After the new release comes out (likely next week), you will have to refactor your code to import from firebase/auth/web-extension instead of firebase/auth.

Guys, CWS now considers the compressed Firebase SDK code to be 'obfuscated.' My two extensions have already received a 'rejected' notification (they took 2-3 working days for the review).

I would suggest creating a new issue for any other MV3 issues that aren't related to script tag injection. I can tell you right now that at a quick glance I don't seem to be able to find any minified symbols in our main auth dist/ bundles, nor any files with that filename. Are you sure the minification isn't a step in your build tooling? We can discuss this further in a separate issue if you create one.

@patrickkettner
Copy link

patrickkettner commented Jan 26, 2024

@hsubox76 the review process does not consider it to be obfuscated. Thanks for your work getting the extension version of firebase launched!

@NhienLam
Copy link
Contributor

NhienLam commented Feb 1, 2024

firebase/auth/web-extension endpoint is now available in SDK v10.8.0.

You can refactor your code to import from firebase/auth/web-extension instead of firebase/auth.

Please note that the following are not supported when using this new endpoint:

  • popup/redirect operations
  • Phone authentication with reCAPTCHA
  • SMS multi-factor authentication with reCAPTCHA
  • reCAPTCHA Enterprise

If you need to use any of these, you will have to use offscreen documents. For example, https://gist.github.com/patrickkettner/ed4faa346ae351aacc20da4083213f4d shared in the above comment. We will publish a guide for how to perform various login flows using offscreen documents.

@NhienLam NhienLam closed this as completed Feb 1, 2024
@firebase firebase locked and limited conversation to collaborators Mar 3, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.