Hi! Bitwarden is currently looking to update the snap package of the Bitwarden Desktop app, but is unable to do so since we had changed permissions and added an interface / plug which needs permission.
reasoning: This is needed in order to enable shared unlock and biometric unlock. These place a manifest, unix socket, binary, in the browsers nativemessaginghosts directory. Please not that while there are movements to make this possible without permission changes, such as XDG-nm-proxy, these are not yet complete enough to use. (Also, they are not implemented, for the cases they do support). Please see the discussion here: Update permissions for com.bitwarden.desktop to enable shared unlock / browser integration by quexten · Pull Request #1053 · flathub-infra/flatpak-builder-lint · GitHub . Please note, we limited our access to the native messaging directory only, and do not give the snap access to all personal files.
That would be preferred, yes, however firefox by default does not create the directory, so the desktop app creates it if it does not exist. If the user does not use any other native messaging application, then it would not be usable for them without running a command externally to set up the directory.
Thanks @quexten, that clarifies the intent, and the mechanism is right: personal-files emits one owner "<path>{,/,/**}" rwkl rule per entry, with no rule for the parent, so a scoped $HOME/.mozilla/native-messaging-hosts genuinely cant create ~/.mozilla when it is absent.
Where I would like to align before approving: the three Chromium paths have the exact same property: $HOME/.config/chromium/NativeMessagingHosts cant create ~/.config/chromium if missing either, but they’re scoped narrowly, so the “browser dir must pre-exist” constraint is already being accepted there. It would be good to apply the same remedy to Firefox rather than broadening, mainly because $HOME/.mozilla grants write to the whole profile (credentials, cookies, prefs) for all users, auto-connected, which is a big step up from “native messaging directory only.”
In practice the cold-start case is also narrow: using the Firefox host requires the extension installed in Firefox, which implies ~/.mozilla already exists and the scoped path works. So I would lean toward scoping to $HOME/.mozilla/native-messaging-hosts for consistency, does that work on your end? Feel free to correct me if I am missing something
On a side note, this will not work with Ubuntu default desktops for chromium or firefox where both come as a snap and use their $SNAP directory as home by default …
I also think the access should be limited to a Bitwarden specific configuration file, similar to what we did for keepassxc in Personal-files access request for KeePassXC. Other than that, It looks good to me
On a side note, this will not work with Ubuntu default desktops for chromium or firefox where both come as a snap and use their $SNAP directory as home by default …
“Specifically then, the FF snap is actually looking at $SNAP_REAL_HOME/.mozilla rather than its own snap $HOME because that’s where every non-sandboxed app would place them, so on with the rest.”
@0xnishit I think there was some miscommunication on my end. We are not concerned about creating the .mozilla directory when absent, rather the native-messaging-hosts directory, which on mozilla is not created by default, but on chrome, the NativeMessagingHosts directory is created by default. It’s not that the browser dir must pre-exist, but the NativeMessagingHosts directory must.
If we gave permissions to just the native-messaging-hosts directory, then if the directory does not exist itself, a user would have to run a command outside of the sandbox to create it. We are trying to make setup as frictionless as possible here, so a user running a command to enable it feels like a step back.
@ogra Yes, snap-sandboxed browsers are not just yet supported. We want to, but the initial expansion of support includes flatpak browser, flatpak desktop app, snap desktop app (but not snap browsers).
Given that this works on keepassxc, I wonder if snap does not work in the same way that flatpak does…
@jslarraz I’ll note that because we want to support sandboxed browsers (snap, flatpak) just a native messaging manifest is not enough. It works for unsandboxed browser, but for sandboxed browsers, neither the unix socket nor the binary that the manifest tells the browser to invoke are available from within the sandbox. The workaround we found is to place a unix socket into the sandbox’ NativeMessagingHosts directory, along with a copy of the binary that allows the browser extension to talk to the desktop app. So we would have to add those files too for each directory.
I’ll loop back around to this as soon as I can. Thanks all for the feedback so far.
It’s not that Snap the package format works differently, it’s that Ubuntu has a downstream patch to the XDG Desktop Portals that allows for browsers with patches to use that interface to work with native messaging. The Firefox snap has this included by default, and the majority of Firefox snap users tend to be Ubuntu users, so there it works fairly comprehensively.
I swear when I tested the KeepassXC work originally it also worked on the Chromium snap, but apparently, Chromium does not have support and when I’d checked elsewhere, was told it never did.
It’s likely the Firefox Flatpak doesn’t have the patch at all but could be made to have it. If it did though, it’d still only work on Ubuntu & derivatives, because you need the system integration side of it which Flatpak/Snap themselves don’t provide.
I guess that’s with the intention to get Flatpak browsers to work; with the Ubuntu Portals patch, the KeepassXC snap provides the binary to the host system at /snap/bin/keepassxc.proxy - the sandboxed Firefox snap then doesn’t ever need to access that binary directly, because functionally it’s the portals/system operating outside the sandbox that create a bridge.
So for Firefox snap with BitWarden snap, you shouldn’t need to create a binary in Native Messaging folder the or expose a socket; but I can see why on Flatpak that looks essential, because the browsers wouldn’t have the Native Messaging Portals support. For non-sandboxed browsers, again, just the Native Messaging manifest should be enough so long as the executable for Bitwardens messaging proxy is exposed as a separate binary in /snap/bin/
You can only have a definition once though which I guess is the issue, so for the broadest compatibility, you’d basically have to treat the Flatpak browser approach as the standard approach for everything. Edit: And it’s not guaranteed to work that well with snapped apps if you did, because I don’t think personal-files grants executable permissions to the files it gives access to whereas e.g., home does, so even if Firefox snap has read access to the Native Messaging folder, it might not be able to execute the proxy.
Okay, looks like we’re skipping the current desktop app released until the permission question is resolved. I want to build consensus here on how to move forward.
We understand that XDG Desktop Portals has a solution on ubuntu, and seems to be enabled by default there, but this solution only works on ubuntu, not on other snap installations. (Though, granted, ubuntu is probably the vast majority of snap, other distros tend to use flatpak).
That said, so fair the assumption is that:
We need access to the entire firefox directory to create the NMHS directory
We need access to the entire NMHS directory on chromium based browsers, in order to place the sockets
As @James-Carroll points out, on Ubuntu this can be done by the XDG-Desktop-Portals based approach, however, we don’t have this implemented currently
In my opinion it is a reasonable assumption that a user trusts the Bitwarden snap because it stores all of their passwords. If the snap were malicious, then all of the user’s passwords (and SSH keys) would already be compromised.
On the NMHS vs NMHS + files permission, yes restricting to specific files in the NMHS would be more fine-grained, however, given that the browser is effectively running a binary that the bitwarden-desktop-app writes into the NMHS dir within the browser’s sandbox, this means that the desktop app could place any binary in there. Under the assumption that it were malicious, the entire sandbox could just be compromised by placing the compromised desktop proxy binary.
So, going forward, I see a few paths we can go:
We move forward with auto-connect, in this case i’d actually like to modify the request to:
I have a draft PR that adds support for snap based browsers, and the next release would then add support for: snap to snap communication which would cover most Ubuntu users
This feels reasonable, because users should already place high trust in the Bitwarden snap, given it contains their passwords.
(If we provide the alternative of “install the deb please” this would give the Bitwarden app more permissions, while at the same time introducing more security risks because the deb currently does not support auto-updates, since Bitwarden does not host a repo for it)
Follow-Up improvement:
I will make a task to investigate the XDG-desktop-portal based approach. Once we moved to this approach, we can drop the permissions again.
In case the snapcraft maintainers deem 1. as too risky.
One path forward here would be to accept this, but not grant auto-connect. In this case upstream would add in-product UI to guide the user to grant auto-connect. We would prefer not to have the user run commands in the terminal because this would make it inaccessible to non-technical users.
If 2.1 does not work, we would not support biometrics for the time being, until we have time to investigate xdg-desktop-portals for IPC.
I can’t comment on the security review aspects since I’m not with Canonical, but I am thinking that adding an executable in the Native messaging manifests folder could have merit for user experience.
I think perhaps rather than adding the raw binary and socket to the Native Messaging folder, you might be able to get by with a shell script something similar to:
#!/bin/bash
if [[ -f /.flatpak-info ]]
then
flatpak-spawn --host snap run bitwarden.proxy
else
snap run bitwarden.proxy
fi
This still relies on the BitWarden snap defining a second executable to go in /bin/snap
My thoughts are that this might provide enough flexibility to cover unsandboxed, Flatpak, and Snap browsers
Un-sandboxed browsers would just run as normal without portals, like how KeepassXC snap would work with e.g., Google Chrome
Flatpak browsers would call out the sandbox and run without portals, I’m unsure if the browsers would need to add have permissions granted to use that command but it’s likely they already have them if it’s not a default capability.
Snap browsers with the downstream portals patch would use the portals, so would be like the KeepassXC snap with the Firefox snap.
Snap browsers without the downstream portals patch likely can’t benefit from that approach because they’ll either not have personal-files granted to let them access your binary, and I still think personal-files doesn’t actually grant executable permissions if they did, and then on top I think snap run doesn’t work inside snaps themselves.
This would mean you could also hide the socket, since it’d be an implementation detail kept entirely inside the snap runtime.
I could be wrong, but I am under the impression that browsers could use that functionality and the Flatpak sandbox doesn’t deny it by default, even accounting for the fact that yes, it’s a trivial sandbox escape mechanism (and why AppArmor actually blocks snaps trying to use the underlying interface on our end)
FWIW, I’ve currently been without a PC for a few months but I’m expecting one delivered this week so can take a more direct look in the next week or so as I start catching up on backlogs
Thank you @ogra, I’ll remove it from the draft, and retract the request for this path and for edge. I’ve added brave since it was missing in the electron builder config.
From my non official side I personally think this should be eligible for auto connection, with the primary justification being publisher trust (as a a verified snap) and user expectations (as a password manager you already have all the credentials inside your sandbox and so the risk profile shifts towards encouraging better security practises user-side, which this request helps with) - the rest is just implementation details. A key detail being that you’re not placing binaries in the hosts $PATH, so the only way that potential escape can be utilised is by an extension reading the manifest to find it, and the browsers have their own permissions and signature checks going on, so the risk IMO is minimal because the only extension that should be interacting with that manifest are Bitwardens own where again the trust is already significant.
If flatpak-spawn can’t be used then it might mean when trying to get the Firefox snap working, you’d have have a UI toggle for users where the .json is rewritten with a different executable path, but the files would be the same and the justification the same (I don’t think you can rewrite the binary as snapped browsers can’t execute it so that’s using the portals approach with a second /snap/bin/ executable)
I’ll try play around with Flatpak on the weekend and let you know if anything pops up (primarily I’m still wondering how Joplins Flatpak is making use of flatpak-spawn here, or whether it historically worked differently and changed since and the README is out of date?)
So community +1 from me, which might be a +0 in reality but I think the benefits to users and ecosystem outweigh any risks here, the balance is favourable
Thanks everyone and @James-Carroll , the portal explanation is the key piece here. Let me take the directory-creation assumption first, since it’s load-bearing, then the snap-browser paths.
“We need the whole .mozilla to create the NMHS directory”
This isnt required on current snapd, because snapd creates the missing intermediate directories for you. Since the 2.62 cycle (LP #1997598:https://bugs.launchpad.net/snapd/+bug/1997598), personal-files auto-creates any missing directories between $HOME and a write target on first run by a non-root user. It is now documented behaviour (ref: https://snapcraft.io/docs/personal-files-interface) If there are missing directories between $HOME and the target file or directory, these are created automatically when the associated application is first run by a non-root user.
So I wouldd ask to scope the Firefox entry to $HOME/.mozilla/native-messaging-hosts to match the three Chromium entries.
The snap-browser paths ($HOME/snap/firefox/common/.mozilla, $HOME/snap/<browser>/common/.../NativeMessagingHosts)
I would push back on these specifically. -1 from my end on these files, They’re cross-snap writes, with Bitwarden reaching into another snap’s private SNAP_USER_COMMON, which breaks the isolation boundary between snaps and couples Bitwarden to each browser snap’s internal layout. That’s outside what personal-files is intended for. And as @James-Carroll mentioned, it is the wrong mechanism for Ubuntu: the XDG-desktop-portal native-messaging patch already bridges snap browsers to a host-side proxy (the KeePassXC snap does this via keepassxc.proxy ), so nothing needs to be written into a browser snap’s sandbox, since the portal handles it outside confinement.
I would say, for now, my preference is a scoped auto-connect now for these file paths, plus the portal work for snap browsers: