Closed Bug 1414887 Opened 7 years ago Closed 7 years ago

Pass profile location to native messaging apps

Categories

(WebExtensions :: Untriaged, defect)

56 Branch
defect
Not set
normal

Tracking

(firefox57 wontfix)

VERIFIED WONTFIX
Tracking Status
firefox57 --- wontfix

People

(Reporter: n.gollenstede, Unassigned)

Details

User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0 Build ID: 20171024165158 Steps to reproduce: I'd like to propose that Firefox (and preferably other Browsers) pass the location of the current profile, the contacting extension and the cache directory to applications started with the WebExtension native messaging API. All three values can be interesting for the spawned process for various reasons. The use case I have is that I need to locate the extension package to execute contained scripts in node.js. Relying on the extension to message the scripts or the extension location would be quite a big security issue. I could also imagine that a privacy extension wants to clear/manipulate the cache or that a video transcorder wants to store a copy of ffmpeg in the profile folder. To avoid backwards-incompatibility, I'd suggest to set these values as environment variables. Actual results: Currently it is somewhere between hard and impossible to reliably get these values. The best I could come up with is reading the `MOZ_CRASHREPORTER_EVENTS_DIRECTORY` environment variable and going two folders up for the profile directory. Extensions (of which the process gets passed the id) are usually stores in the `./extensions/` folder therein. The cache directory is either placed inside the profile (for non-default locations passed via the cli) or in a OS specific folder whose path is related to that of the profile. Unfortunately, there are Firefox builds that don't set the `MOZ_CRASHREPORTER_EVENTS_DIRECTORY` for themselves, so it won't be inherited by the spawned processes. And obviously Chrome does things entirely different. Expected results: Firefox sets something like the following environment variables for the spawned native messaging apps: MOZ_PROFILE_DIR: the Profile Folder on about:support MOZ_EXTENSION_FILE: full path to the extenion `.xpi` OR MOZ_EXTENSION_DIR: full path to the unpacked extension, e.g. loaded via about:debugging MOZ_CACHE_DIR: fill path to the folder containing the `chache2`folder, or the `cache2` folder itself
The format of the profile is a Firefox implementation detail and the things you're proposing to do with the profile are not supported through any public/documented methods. You can manipulate the cache from within the browser using the extension browsingData apis. And the Firefox profile is not an appropriate place for your native application to keep a copy of ffmpeg. And the "big security issue" isn't very clearly explained...
Status: UNCONFIRMED → RESOLVED
Closed: 7 years ago
Resolution: --- → WONTFIX
Status: RESOLVED → VERIFIED
Maybe asking for the cache folder was taking it a bit too far, but I think I have valid use cases for the other two. # Extension location > the "big security issue" isn't very clearly explained Indeed is wasn't. I have spend quite some time trying to come up with a reasonably secure and easy way of distributing extensions that require capabilities outside the browser, i.e native messaging. A general problem I see with native messaging is that the user would always need to have compatible versions of the extension and the native program installed. This can either be achieved if, at any given time, there is only a single latest version, and both components always update to exactly that version at the same time, which requires considerable effort and infrastructure in itself, or if one component is able to update the other. I think that is the scenario the Chrome devs had in mind when designing the native messaging APIs was that the user already has a particular program installed and that program wants to integrate itself into the browser. In that case, the program can choose from a number of ways to install an extension in the browser and update it on its own terms independent of the browser. As I see it, so far there is no good solution for the reverse case, where the extension is the primary software which only needs some help from a native program to achieve its goals. In that case it would make sense for the extension, which is being updated by the browser e.g. from AMO, to bring the native program to its own version. One pretty straight forward solution to do this is to have users install a helper app that accepts code passed by extensions and evaluates the code (see e.g. https://github.com/andy-portmen/native-client). The "big security issue" here is that if an attacker gains control over one of the white listed extensions, he could potentially have the extension pass his own code and thus gain control over most parts of the computer. Firefox, the WebExtension framework and the code reviews on AMO take great effort and care to avoid code injection inside of extensions. This however is *much* worse. And is being done in practice! Now, I think I have fond and implemented a solution that largely mitigates this code injection risk: Instead of the extension passing code it chooses at runtime (possibly compromised) to the native program, the program located the extension package and makes the files within (which are much more likely to actually have been written by the developer) executable. If none of the files in the extension evaluate further code by string, and the attacker cant control the files where the extension is located, code injection should not be possible. I have implemented this https://github.com/NiklasGollenstede/native-extand it is working pretty well. The most difficult and fragile part of it is locating the extension, either packed or unpacked on the local file system: https://github.com/NiklasGollenstede/native-ext/blob/master/browser.js Having a user setting in the extension to tell the native program the location of the extension is not an option. A compromised extension could use the browser.downloads API to place a file extensions/@compromisedExtensionId.xpi in the downloads folder and then claim that the downloads folder is the profile root. There would be no way for the native program to tell that this is not actually true, so it would execute the attackers code. Bottom line, it would be very convenient if the browser would tell the native program the extension location via a documented and stable channel, e.g. the suggested environment variables. # Profile location Make changes to the `chrome/userChrome.css` and `userContent.css` files. Both have been around for ages and I very strongly hope that Mozilla has no plans to change that, after all, just a few versions back the userContent.css was made compatible with e10s. They are quite easy to understand, I don't think their semantics are likely to change and they are even documented: http://kb.mozillazine.org/index.php?title=UserChrome.css Wouldn't it be nice to have an extension that helps users manage the styles in those files, now that (the original) Stylish for Firefox will stop working? https://github.com/NiklasGollenstede/re-style All it needs to know is the location of the current Firefox profile. I have actually put a lot of thought and effort into this, so I would appreciate it if you don't simply leave this as a WONTFIX. Thanks!
(In reply to Niklas Gollenstede from comment #2) > As I see it, so far there is no good solution for the reverse case, where > the extension is the primary software which only needs some help from a > native program to achieve its goals. In that case it would make sense for > the extension, which is being updated by the browser e.g. from AMO, to bring > the native program to its own version. This is a deliberate part of the design of WebExtensions generally and native messaging in particular. Extensions run in a sandbox and we don't want them to contain arbitrary code that runs in a privileged context (whether that is code that runs in privileged parts of the browser or in other applications that don't sandbox code from the network the way a web browser does). It is of course not a problem we can solve in general since we can't control what people do in native applications. As you point out a native application can just execute arbitrary code or commands from an extension, I would classify that as an unsafe application that I would not personally be inclined to install. > Now, I think I have fond and implemented a solution that largely mitigates > this code injection risk: > Instead of the extension passing code it chooses at runtime (possibly > compromised) to the native program, the program located the extension > package and makes the files within (which are much more likely to actually > have been written by the developer) executable. If none of the files in the > extension evaluate further code by string, and the attacker cant control the > files where the extension is located, code injection should not be possible. Perhaps I don't understand the scenario you're describing here but if an attacker manages to replace your extension with a compromised version, there's nothing to prevent them from modifying any individual files inside the extension. I think if you really want to go down this path your best bet would be to implement your own form of code signing. i.e., generate a keypair and embed the public key in your native application, then sign any code that will be execute by the native application with the private key and send both the code and the signature to the native application and verify the signature before executing the code. An attacker who can put new code into your extension won't actually be able to get the native application to execute it since they can't sign it with the private key that only you have. > # Profile location > > Make changes to the `chrome/userChrome.css` and `userContent.css` files. > Both have been around for ages and I very strongly hope that Mozilla has no > plans to change that, after all, just a few versions back the > userContent.css was made compatible with e10s. They are quite easy to > understand, I don't think their semantics are likely to change and they are > even documented: http://kb.mozillazine.org/index.php?title=UserChrome.css > Wouldn't it be nice to have an extension that helps users manage the styles > in those files, now that (the original) Stylish for Firefox will stop > working? > https://github.com/NiklasGollenstede/re-style > All it needs to know is the location of the current Firefox profile. The documentation on mozillazine is not sponsored or endorsed by Mozilla. My understanding is that those files are supposed on a best-effort basis, which means no promises that anything in them will continue working from release to release. I think that modifying those files from a native messaging application also has a pretty serious usability problem since the browser has to be running for your extension and your native application to run but then you generally need to restart the browser for any changes to take effect. In short, this isn't something that we can justify adding features to support.
> if an attacker manages to replace your extension with a compromised version, there's nothing to prevent them from modifying any individual files inside the extension. Yes, but if an attacker got far enough to write to the extensions directory in my Firefox profile, I have already lost control of my system. But assuming an attacker is *not* able to do that, compromising the code running in the extension won't allow him to infect the entire system. > implement your own form of code signing. I considered that, but keeping a key secret (while still using it) is not trivial. I'd like the solution to be easily adaptable by other developers as well, which would require multiple keypairs and the loss of any one of them, which is bound to happen sooner or later, would expose the users. Sou you would need a revocation strategy, and so on. Besides that, implementing crypto isn't something one should take easy. And there wouldn't be any gain in security compared to the approach I choose. If an attacker is able to write to arbitrary disk location, he could just replace the public keys with his own. Knowing the extensions installation location would be much easier. > modifying those files from a native messaging application also has a pretty serious usability problem since the browser has to be running for your extension and your native application to run but then you generally need to restart the browser for any changes to take effect. The UX certainly isn't perfect, but there just isn't any way of (fully) customizing Firefox on the fly anymore. The only upside here is that restarting Firefox is a lot faster now than it used to be. > In short, this isn't something that we can justify adding features to support. In my opinion that is very unfortunate, especially because I don't think it will stop people from using native messaging the ways I described. It will just be a bit more difficult to implement and maintain. And potentially a lot less secure.
(In reply to Niklas Gollenstede from comment #4) > > if an attacker manages to replace your extension with a compromised version, there's nothing to prevent them from modifying any individual files inside the extension. > > Yes, but if an attacker got far enough to write to the extensions directory > in my Firefox profile, I have already lost control of my system. But > assuming an attacker is *not* able to do that, compromising the code running > in the extension won't allow him to infect the entire system. Now I don't understand the threat you're describing. I thought you were talking about an attacker stealing your AMO credentials or compromising the site from which you're serving updates and pushing a new version. An attacker with access to the local file system can't change the extension contents without breaking the signature check. > In my opinion that is very unfortunate, especially because I don't think it > will stop people from using native messaging the ways I described. It will > just be a bit more difficult to implement and maintain. And potentially a > lot less secure. We can't stop people from abusing native messaging in this way, but your analysis about the security tradeoffs is incorrect. Such a native application wouldn't be made any more secure by making it easier to find the extension xpi file.
> An attacker with access to the local file system can't change the extension contents without breaking the signature check. Exactly. So if replacing the extension file in it's original location is not possible, it would be very attractive to be sure to only load exactly that file. There would be no guarantee that the developer didn't put unsafe code inside, but at least it could not have been tempered with. If it were, the browser would not have loaded the extension. > Such a native application wouldn't be made any more secure by making it easier to find the extension xpi file. If the alternative is that the extension directly passes code strings or even just it's location tot he native app, then knowing the location of and executing only the file that is already checked by and loaded in the browser is defensively more secure. That file could not have been changed by an attacker, and if the developer released something severely insecure, then there already are revocation/blacklisting mechanisms.
Without the profile location, it is hard to call NSS_Init and get user certificates. This is needed to support window.crypto.signText.
Perhaps setting environment variables is not appropriate. What about a runtime.getProfileInfo() function? Would it be wontfix too?
Flags: needinfo?(aswan)
We won't be exposing the profile path to native apps in any way.
Flags: needinfo?(aswan)
Why not let the user decide? WebExtensions need permissions; this could be one more. It is the way to declare what the native back end tries to do. So, is permission a wontfix?
Users aren't equipped to decide whether applications should be interfering with the internal data structures of a profile directory.
The issue here isn't about permissions, its about not having a credible use case to justify maintaining the code for this. And to be clear, "it won't take very much code" isn't a valid reason to do it.
> its about not having a credible use case signTextJS plus https://addons.mozilla.org/en-US/firefox/addon/signtextjs-plus/
Although I have presented a credible use case, passing the profile location is not the best way to support such case. However, since Mozilla has banished signatures with Firefox certificates (bug 1435269) and no standard covers this use case, passing the location to a native application is the only way. Therefore, do not blame native applications for acting in seemingly obscure ways because you give no choice to support legitimate cases.
Product: Toolkit → WebExtensions
You need to log in before you can comment on or make changes to this bug.