16

The latest update to Firefox (41.0b1) aggressively blocks the installation of unverified extensions, namely HTTPS Everywhere and Privacy Badger.

How might I be able to force these extensions to install? Is there a setting inside about:config I could temporarily toggle?

Mozilla highlights this change to Firefox here, noting its previous efforts to be inefficient at corralling malicious extensions.

0

4 Answers 4

21

Yes, there is a setting in About:config, its name is xpinstall.signatures.required. Double-click on the preference name so that its value is set to false. Now you can install unsigned extensions in Firefox. A browser restart is not needed.

8
  • 2
    Fantastic! This fix will suffice until EFF and others have there extensions verified.
    – VitaminYes
    Aug 12, 2015 at 21:02
  • 1
    This also won't work after version 43+. :( Aug 6, 2016 at 19:47
  • Despite many sources saying it won't work in recent FF, it worked for me in 48.0 on Linux. I had to open the addons page and drag the xpi file there. Aug 9, 2016 at 13:51
  • @ThatBrazilianGato: is is not working for me on Win7 FF48.0 :(
    – glavić
    Aug 16, 2016 at 13:37
  • 4
    That's it for me. Bye Firefox, loved you since version 0.6. :-( Hope there will be a workaround some day.
    – andreas
    Aug 30, 2016 at 21:59
3

Apparently on Firefox 60 and above neither the xpinstall.signatures.required nor the config.js trick outlined above works (Mozilla, keel over please!).

The Russian forum that's referenced above apparently mentions a solution for these versions of Firefox as well. So put this into config.js instead which you then save to C:\Program Files\Mozilla Firefox

//
try {(code => {
    var {classes: Cc, interfaces: Ci, utils: Cu} = Components;
    var jsval, evl = true, re = e => Cu.reportError(e), imp = name => {try {
        return Cu.import(`resource://gre/modules/addons/${name}.jsm`, {});
    } catch(ex) {}}
    if ((jsval = imp("AddonSettings"))) {
        jsval.AddonSettings = {ADDON_SIGNING: false, REQUIRE_SIGNING: false, ALLOW_LEGACY_EXTENSIONS: true};
        try {evl = jsval.eval("this") === jsval;} catch(ex) {evl = false;}
    }
    var jsvals = ["XPIProvider", "XPIInstall"].map(imp).filter(i => i);
    jsvals[0].AddonSettings && lockPref("extensions.allow-non-mpc-extensions", true);
    jsvals[0].signaturesNotRequired = true;

    if (evl) return jsvals.forEach(jsval => {try {jsval.eval(code);} catch(ex) {re(ex);}});

    var sl = Cc["@mozilla.org/moz/jssubscript-loader;1"].getService(Ci.mozIJSSubScriptLoader);
    Cu.importGlobalProperties(["URL", "Blob"]); var url = URL.createObjectURL(new Blob([(code)]));
    jsvals.forEach(jsval => {try {sl.loadSubScript(url, jsval);} catch(ex) {re(ex);}});

})(String.raw`((vzss, pckg) => {
    var trueDesc = {enumerable: true, value: true};
    typeof Extension == "function" && Object.defineProperty(Extension.prototype, "experimentsAllowed", trueDesc);
    "AddonInternal" in this && Object.defineProperty(AddonInternal.prototype, "providesUpdatesSecurely", trueDesc);
    this.isDisabledLegacy = () => false;
    if ("XPIDatabase" in this) this.XPIDatabase.isDisabledLegacy = () => false;
    try {SIGNED_TYPES.clear();} catch(ex) {};

    if (!vzss && !pckg) return;

    var re = /\x06\x03U\x04\x03..(\{[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\}|[a-z0-9-\._]*\@[a-z0-9-\._]+)0\x82\x02"0\r\x06\t/i;
    var getUUID = () => {
        var gen = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator);
        return (getUUID = () => gen.generateUUID().toString())();
    }
    var getIdFromString = str => {
        var match = str && str.match(re);
        return match ? match[1] : getUUID();
    }
    var getState = arg => ({
        signedState: AddonManager.SIGNEDSTATE_NOT_REQUIRED,
        cert: typeof arg == "object" ? arg : {commonName: arg}
    });
    var checkAddon = addon => {
        if (addon.id || (
            "_installLocation" in addon
                ? addon._installLocation.name == KEY_APP_TEMPORARY
                : addon.location.isTemporary
        ))
            return getState(null);
    }
    var getRoot = () =>
        !AppConstants.MOZ_REQUIRE_SIGNING && Services.prefs.getBoolPref(PREF_XPI_SIGNATURES_DEV_ROOT, false)
            ? Ci.nsIX509CertDB.AddonsStageRoot : Ci.nsIX509CertDB.AddonsPublicRoot;

    if (vzss) {
        var getURI = file => {
            var jsval = Cu.import("resource://gre/modules/addons/XPIProvider.jsm", {});
            return (getURI = file => jsval.getURIForResourceInFile(file, "META-INF/mozilla.rsa"))(file);
        }
        var getIdFromFile = file => {
            var str, is = {close() {}}, sis = {close() {}};
            try {
                is = Services.io.newChannelFromURIWithLoadInfo(getURI(file), null).open();
                sis = Cc["@mozilla.org/scriptableinputstream;1"].createInstance(Ci.nsIScriptableInputStream);
                sis.init(is);
                str = sis.readBytes(sis.available());
            } catch(ex) {}
            sis.close(); is.close();
            return getIdFromString(str);
        }
        this.verifyZipSignedState = function verifyZipSignedState(aFile, aAddon) {
            var res = checkAddon(aAddon);
            return res ? Promise.resolve(res) : new Promise(resolve => {
                var callback = {openSignedAppFileFinished(rv, zipReader, cert) {
                    zipReader && zipReader.close();
                    resolve(getState(cert || getIdFromFile(aFile)));
                }};
                gCertDB.openSignedAppFileAsync(getRoot(), aFile, callback.wrappedJSObject = callback);
            });
        }
    }

    if (pckg) Package.prototype.verifySignedState = function verifySignedState(addon) {
        var res = checkAddon(addon);
        return res ? Promise.resolve(res) : new Promise(resolve =>
            this.verifySignedStateForRoot(addon, getRoot()).then(({cert}) => {
                if (cert)
                    resolve(getState(cert));
                else
                    this.readBinary("META-INF", "mozilla.rsa").then(
                        buffer => resolve(getState(
                            getIdFromString(String.fromCharCode(...new Uint8Array(buffer)))
                        )),
                        () => resolve(getState(getUUID()))
                    );
            }, Cu.reportError)
        );
    }
})(
    "verifyZipSignedState" in this, typeof Package == "function"
);`)} catch(err) {
    err.message != "Components is not defined" && Components.utils.reportError(err);
}

Then you have to add this to the config-prefs.js file saved to C:\Program Files\Mozilla Firefox\defaults\pref

pref("general.config.obscure_value", 0);
pref("general.config.filename", "config.js");
pref("general.config.sandbox_enabled", false);

It's been tested to work on FF 66.0.3. Unfortunately it won't bring your addons and themes magically back, but at least it re-enables the option of re-installing them. Better than anything Mozilla has to offer anyway, as they don't seem to particularly care despite the fact that their forums are being flooded with complaints about this problem.

5
  • Look, if you really really want this, don't install random hacks, just use a Nightly where the signatures.required preference string is actually enabled. May 5, 2019 at 10:18
  • 2
    And why should I? Up until now I was completely fine with using what I thought to be stable versions of FF where I only installed legitimate and genuine addons straight from Firefox's official addon site. And now all these addons (and themes, for Christ's sake!) have stopped working all of a sudden. I'm sorry but instead of installing a potentially even more broken version of FF I prefer something that makes my current installation work instead.
    – CoolKoon
    May 5, 2019 at 20:05
  • P.S. The addons have stopped working on the Android version of FF (v66.0.2) running on my phone as well, but curiously enough the xpinstall.signatures.required still seems to work there.
    – CoolKoon
    May 5, 2019 at 20:08
  • 1
    THANK YOU! This is the current working answer for Firefox 98. Mar 27, 2022 at 6:53
  • What are the relevant paths on Linux?
    – einpoklum
    Mar 21, 2023 at 20:17
1

On Firefox 48 and above, this method doesn't work. Instead you should create two config files inside Firefox directory.

  1. Create config.js file in notepad (make sure file extension is .js and not .txt):

    //
    try {
    Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm", {})
    .eval("SIGNED_TYPES.clear()");
    }
    catch(ex) {}
    
  2. Move config.js to your Firefox installation directory:

    Windows: C:\Program Files\Mozilla Firefox
    (or C:\Program Files (x86)\Mozilla Firefox )

    Linux: /usr/lib64/firefox-< version >
    (or /usr/lib/firefox-< version > )

    Mac: /Applications/Firefox.app

  3. Create config-prefs.js in notepad:

    pref("general.config.obscure_value", 0);
    pref("general.config.filename", "config.js");
    
  4. Move config-prefs.js into Firefox defaults\pref directory.
    (e.g. C:\Program Files\Mozilla Firefox\defaults\pref)

  5. Restart Firefox.

  6. Drag the unsigned XPI into Firefox window, or use the "Install Add-on From File" option, in the settings of Firefox Add-ons.


Originate from this source: https://forum.mozilla-russia.org/viewtopic.php?id=70326

2
  • Unfortunately this method doesn't seem to work on FF 66.0.3 64-bit. It'd be sorely needed now that Mozilla has messed up BIG time.
    – CoolKoon
    May 4, 2019 at 19:24
  • This no longer works. See other answer mentioning edits to this. Mar 27, 2022 at 6:55
0

tldr: Mozilla completely removed possibility to install unsigned extensions in "release" software channel.

Old question, but I came across this problem today. I just wanted to install and test my first theme that I am creating here on my local firefox... no luck. After spending half the day web searching a possibility to install unsigned addons it looks like there is None! (I did not try the hacking script from @CoolKoon's answer above)

mozilla states here:

What are my options if I want to use an unsigned add-on? (advanced users): Firefox Extended Support Release (ESR), Firefox Developer Edition and Nightly versions of Firefox will allow you to override the setting to enforce the extension signing requirement, by changing the preference xpinstall.signatures.required to false in the Firefox Configuration Editor (about:config page). There are also special unbranded versions of Firefox that allow this override. See the MozillaWiki article, Add-ons/Extension Signing for more information.

Also the webextension development documentation says the same:

Unsigned extensions can be installed in the Developer Edition, Nightly, and ESR versions of Firefox, after toggling the xpinstall.signatures.required preference in about:config. To use this feature your extension must have an add-on ID.

My personal solution for myself: install ESR (and try to move over my profile)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .