-
-
Notifications
You must be signed in to change notification settings - Fork 203
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
webextensions: add a portal for managing WebExtensions native messaging servers #705
base: main
Are you sure you want to change the base?
Conversation
This looks like an implementation of the easy parts of #655, which is missing the hard parts, most notably a security model: if I'm reading correctly, this gives every Flatpak/Snap app access to all webextensions, and trusts every Flatpak/Snap app to say what domain it is acting on behalf of. Of course it's useful to have an implementation of the easy parts, but it cannot be merged without someone doing the harder work to design a security model for it, and then implement that security model. I certainly wouldn't want anyone to get the impression that this PR is basically finished and just waiting for reviewers to say yes. At the risk of stating the obvious, it is not OK for an untrusted app |
The answer to "is this a static permission" or "is this a user prompting issue" is, IMO, both. A sandboxed browser is the one responsible for checking whether the appropriate sites are or aren't accessing the native messaging hosts they are permitted to. The http/JS/... session can't be moved out of the browser, there's nothing the portal can do to know or verify the origin domain that I can reasonably think of. So the static permission is "I trust this browser to have some internal confinement and be able to identify a site to me correctly" -> "therefore it may speak to the native messaging host portal and identify a site to the user". The user consent would be specific and timely "[Browser] wants [Website] to access [Application] on your system." and provides the user the choice to verify several things:
|
I agree that the access control side needs to be completed: that's why I marked the PR as draft to indicate that it wasn't ready to be merged. I published this more so there would be something to get feedback on the API and be able to test if it was fit for purpose. As for the permission dialog, the pieces of information we have for a prompt dialog are:
I think (1) and (4) would be the most important pieces of information to include in the access dialog. The extension ID is not likely to be useful to the user (especially in the Chromium case, or Firefox extensions still using UUIDs as their IDs). If we want to provide a human readable name for the extension, then the browser would need to provide that to the API. That said, I'm not sure whether it makes sense to include information about the extension in the access dialog, since it is effectively self asserted data from an untrusted client: we're simply using it in the portal implementation to help the browser implement its own security policies within the app sandbox. |
Also, in follow-up to #705 (comment), the native messaging host is invoked by a browser extension rather than a web page. So in the case of the chrome-gnome-shell native messaging server, it isn't the extensions.gnome.org website talking to it directly: rather it talks to an extension that in turn invokes the native messaging server. So I don't think it makes sense to include website details in the access dialog either. |
I'm not sure this is quite right. The native hosts are installed on the host system, or if they are exported via a sandboxing runtime such as Flatpak or Snap, the metadata provided around naming (or icons, etc) is at an equivalent trust level to eg, the names/icons in a .desktop file, which the portal already relies on heavily (ie via XdpAppInfo) for user decisions around access/launching/etc. (Of course, whether Flatpak should be exporting app icons and descriptions unmodified is a separate question, the security model there seems to be about filtering by app ID, which is not what the user sees, but that's not a regression introduced by this PR so I wouldn't get bogged down in it. If we look at eg exporting native message hosts from a Flatpak, this would need some attention.)
Oh yes. That's a bit less useful indeed. Is there a way we can allow the browser (ie trusted enough to have the static permission) to provide optional additional info here that identifies the extension in a slightly better way than the ID? Presumably our fallback implementation of this is a stub launcher that just calls to the proxy, and the sandboxed browser is unaware that there's any sandbox exit going on (I got chrome-gnome-shell working once on this basis) but if we move to submitting patches we might be able to do better? |
If browsers have static permission to allow access to native messaging servers the native messaging servers already only have to deal with trusted parties (i.e. everyone talking to a native messaging server is authenticated as a browser). Similarly if flatpak only allows to export native messaging servers with the name matching the appid, the browsers only deal with authenticated parties. Any kind of dynamic permission dialog in the portal can only show the appid of the browser and the appid/name of the native messaging server which is completely redundant. We can't show any relevant information in the portal because we don't understand the mechanisms of the native messaging server. Instead the browser can (and probably should) ask the user if it's okay for a specific add-on to talk to a specific app/native messaging server. (If we didn't have static permissions for browsers it would be the responsibility of the native messaging server to ask the user if it want's to allow a specific request from a specific browser/app.) |
I feel like this is leaving out an important aspect of native messaging hosts, which would be the browser communicating with other Flatpaks (e.g. Chrome talking to 1password). That's technically already possible & I have some PoC code locally in that direction, but if there's going to be a full portal, it probably needs to handle that case too to have a unified implementation. |
a21ad86
to
21113e2
Compare
I've updated the PR to add the suggested permission checks: both a static check in The text in the access dialog could use some work, as I'm not sure how best to describe the native messaging server in a way that would be meaningful to the user. If it's decided that a static permission is sufficient, then I guess we can remove this check and this wouldn't matter. |
It would be useful to add a |
I'm playing with this, and I noticed that if I manually kill the spawned process, the portal crashes with the following message:
|
An update on my work to integrate this in Firefox: I've submitted a WIP patch that's mostly functional, but I still need to figure out why reading/writing from/to the passed file descriptors fails, Firefox complains that the files are closed. |
And another update: I figured out the file descriptors issue, so this is now working as expected, in my limited testing. I am now building a snap with this patch to test under proper confinement. |
A note for my future self: when testing this against e.g. the firefox snap and the chrome-gnome-shell native connector, the following command is useful to grant the required permission:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jhenstridge can you elaborate a bit more on the TODO
around checking whether the requesting app is a browser in xdp_app_info_is_web_browser()
?
src/webextensions.c
Outdated
hosts_path_str = g_getenv ("XDG_DESKTOP_PORTAL_WEB_EXTENSIONS_PATH"); | ||
if (hosts_path_str == NULL) | ||
{ | ||
hosts_path_str = "/usr/lib/mozilla/native-messaging-hosts:/etc/opt/chrome/native-messaging-hosts:/etc/chromium/native-messaging-hosts"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this also include /etc/opt/edge/native-messaging-hosts
for Microsoft Edge?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm honestly not sure about this one. If we have any messaging hosts supporting Edge, would the json files they install for Chrome likely cover the IDs of the Edge extension too?
a90b52d
to
8df492e
Compare
b970156
to
643831a
Compare
Thanks for merging the fix for the access dialog. In my testing, I'm still consistently seeing the following problem: the first time the user is prompted for authorization and accepts, the portal will spawn the native connector and pass the file descriptors to the client (firefox snap in my tests), but the client sees the file descriptors as closed. Closing the client and re-opening it doesn't help. Only when the portal is terminated and restarted does communication through FDs start working normally. |
And with the following patch to grant authorization right away instead of prompting the user, the problem goes away: --- a/src/webextensions.c
+++ b/src/webextensions.c
@@ -392,7 +392,7 @@ handle_start_in_thread (GTask *task,
}
app_id = xdp_app_info_get_id (request->app_info);
- permission = get_permission_sync (app_id, PERMISSION_TABLE, arg_name);
+ permission = PERMISSION_YES;
if (permission == PERMISSION_ASK || permission == PERMISSION_UNSET)
{
guint access_response = 2; |
dd10691
to
fd77dae
Compare
557d3c1
to
9c0fc43
Compare
…ng servers. This is intended to provide a way for a confined web browser to start native code helpers for their extensions. At present it can start the servers installed on the host system. But in future this could be extended to cover sandboxed native messaging servers too.
…n the wrong state. This could occur if the session is closed between when the task is scheduled and when it is run.
This ensures the session won't be freed while the callback is running, as could happen when close_sessions_in_thread_func() runs. While this creates a reference cycle, it will be broken when the session is closed.
Firefox also documents /usr/lib64/mozilla/native-messaging-hosts as part of the search path. Also include locations based on xdg-desktop-portal's install location.
…ession. At this point, the browser has signalled the native messaging host to exit by closing its standard input. If the process is still running when the browser closes the session, then it is not responding.
…ther to provide Chromium-ish or Mozilla-ish behaviour This affects the following behaviour: 1. the search path for manifest files. 2. whether to match the "allowed_origins" or "allowed_extensions" key. 3. the command line arguments passed to the native messaging server. The tests have also been updated to use a shell script as the test native messaging server. Previously we just used /bin/cat, since it would stick around until its standard input was closed. This broke once we started passing arguments to the server. So now use a shell script that calls cat with no arguments.
While Chromium based browsers are more common, we only have an implementation for Firefox for now, which is not setting this option.
To help folks looking to work on the Web Extensions portal without prior familiarity with the XDG Desktop Portal and related code-bases like one of its main dependencies GLib and its object system.
Explain the session closure behaviour from browsers' perspective and link to the document about Firefox's implementation. Also, add references about arguments passed to the native executable in the Mozilla/Firefox and Chromium modes.
… manifest search path https://bugzilla.mozilla.org/show_bug.cgi?id=259356 Also add a comment in get_manifest_search_path about the importance and explanation of why the searched locations must be inaccessible to the sandboxed browsers.
9c0fc43
to
21e3a9a
Compare
This is an implementation of a slightly modified version of the interface proposed in #655 for starting WebExtensions native messaging servers on behalf of a confined web browser.
The main change was to remove the use of Request objects, as I'm not waiting for a backend impl server to do the work. It might be worth adding that back though to give more flexibility in the future though.
There are some missing features at present:
Fixes #655.