1

I have a Chrome Extension in development, locally which is a React application.

I have set up a CI/CD pipeline so that the React app is built with yarn build to produce the dist directory containing the app files and the manifest.json. The pipeline then uses this npm package to create the .crx file and upload it to a public storage location along with the update.xml file which has been updated with a new version number and URL to the new .crx file.

I created a private key (key.pem) locally and stored in a key vault so that the "packing" job in CI pipeline uses the same private key each time. The public key has been added to the manifest.json so that the app ID stays the same each time.

Update2.xml

<?xml version='1.0' encoding='UTF-8'?>
<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>
  <app appid='blahblahooaejaldnohkhmaedknkfogn'>
    <updatecheck codebase='https://mypubliccrxstorage.blob.core.windows.net/crx/myapp-1.0.20210702.22.crx' version='1.0.20210702.22' />
  </app>
</gupdate>

manifest.json

{
...
    "manifest_version": 2,
    "version": "1.0.20210702.22",
    "key": "<my-public-key",
...
    "update_url": "https://mypubliccrxstorage.blob.core.windows.net/crx/update2.xml"
}

Steps to install and update:

  1. Go to chrome://extensions/ > developer mode > load unpacked > select local dist directory.
  2. The unpacked extension appears in the list of extensions with app id: blahblahooaejaldnohkhmaedknkfogn
  3. Select the extension and click "Update"

Expected result:

Chrome queries the remote update.xml file, sees a version later than the initially installed version, downloads and installs the new crx file from the specified location.

Actual result:

The extension is not updated.

Note: I downloaded the crt generated by the CI/CD from the storage location and uploaded it here. The public key shown by that online tool matches the value of key in the manifest.json and the calculated app id matches the one in update.xml.

To dig a little deeper I opened Fiddler4 and sniffed the calls made by Chrome. Although I don't understand everything, part of one of the responses was:

<?xml version="1.0" encoding="UTF-8"?><gupdate xmlns="http://www.google.com/update2/response" protocol="2.0" server="prod"><daystart elapsed_days="5296" elapsed_seconds="28389"/><app appid="mgndgikekgjfcpckkfioiadnlibdjbkf" status="error-unknownApplication"/><app appid="apbllhlpimnkljppmmdbiipfbjjimjgj" cohort="1::" cohortname="" status="ok"><updatecheck _esbAllowlist="false" status="noupdate"/></app></gupdate>

That "app id" is not mine (or is that the Chrome app id?), but the status of "error-unknownApplication" perhaps gives some hint as to what is going on.

Dan Cook
  • 1,935
  • 7
  • 26
  • 50
  • It's possible that unpacked extensions are hardwired to their disk location regardless of update_url so you'll have to use another installation mechanism such as a policy for force-installed extensions or setting up a personal web store server. – wOxxOm Jul 02 '21 at 15:11
  • 1
    I think you're right about installing in the "unpacked" way kinda hardwires it to the file system. I found that (unlike Chrome) it is possible to install `crx` files by drag/dropping onto Chromium https://www.chromium.org/getting-involved/download-chromium . When installing this way, clicking the "Update" button does update the extension using the `update.xml` and the new remote `crx` file – Dan Cook Jul 02 '21 at 15:48

2 Answers2

1

No protection setting in Chrome allows an extension to update. This setting also allows to drag and drop .crx into chromium extensions.

Chrome settings

vitkon
  • 1,058
  • 8
  • 13
0

Installing the chrome extension by "Load unpacked" button at chrome://extensions "ties" the install to the file system and doesn't allow for updates.

The extension needs to be installed via the .crt file for updating to work. The ability to do this has been removed in Chrome for security reasons.

However you can use Chrome's developer version, Chromium to install the .crt file by dragging and dropping. Installing in this way allows the extension to be updated using the method in the original question (if everything is configured correctly).

This workaround was acceptable in my case.

Dan Cook
  • 1,935
  • 7
  • 26
  • 50