[HOW TO] Run Firefox *and* KeePassXC in a flatpak and get the KeePassXC-Browser add-on to work

Problem

If KeePassXC is sandboxed in a Flatpak, browsers can only access it, if they are not sandboxed, i.e. installed as an deb/rpm package or similar on the host.
Sandboxing both the browser, i.e. Firefox, and KeePassXC – or at least the browser and installing KeePassXC natively, which you’d actually want for security reasons – is not possible.

TL;DR:

  • this should work out-of-the box: Firefox (host-installed), KeePassXC (flatpak from flathub)
  • this does not: Firefox (sandboxed), KeePassXC (host or sandboxed, does not matter)

I show a workaround that makes it possible to use both configurations.

This problem is shown in various GitHub issues: flathub/org.keepassxc.KeePassXC#29, keepassxreboot/keepassxc#2656, xhorak/firefox-devedition-flatpak#92, keepassxreboot/keepassxc-browser#297, flathub/org.keepassxc.KeePassXC#13, xhorak/firefox-devedition-flatpak#92, this Bugzilla bug, not to mention the many dupes like keepassxreboot/keepassxc-browser#297, keepassxreboot/keepassxc-browser#276, keepassxreboot/keepassxc-browser#102 etc.

Background

If you just want the solution, you can skip this part. But for the curious, I’ll explain the problems we face:

  • KeePassXC creates an UNIX socket in $XDG_RUNTIME_DIR/kpxc_server for applications to listen too. keepassxc-proxy is started – via native messagingby the browser (triggered by the add-on keepassxc-browser@keepassxc.org, i.e. KeePassXC-Browser) and tries to listen on that socket to find messages.
  • If Firefox is not sandboxed, that proxy can start as usual. The only thing it possibly needs to do is get into the KeePassXC flatpak.
  • Flathub KeePassXC has a patch that allows the keepassxc-proxy to be started via flatpak run, i.e. Firefox can now run a
  • That is, so far, why Firefox installed on the host does work…
  • Now why it does not work if Firefox is installed as a flatpak: The very good official Firefox flatpak by Mozilla really does have few permissions for being a browser. E.g. it does not have any generic access to the file system (it uses portals). Anyway, whatever it does, it cannot do one thing: Spawn a process on the host or in another flatpak.

So we could solve that by making wrapper scripts and using flatpak-spawn to let Firefox escape it’s sandbox. However, seeing how lovely and quite securley the Firefox sandbox is already built, I would not dare to destroy that security for such a feature. After all, from a security POV you could then also just install Firefox on the host, yet again.
So glad news ahead: This solution preserves all sandboxes and security aspects!

However, even if we’ve solved the fact of Firefox having to run the proxy, there are more problems. To spoiler, this are the main points we need to solve:

  1. Starting keepassxc-proxy by Firefox (solution: we run it inside the Firefox sandbox)
  2. Allowing Firefox to access the socket of KeePassXC
    Note: At that step, you can already run the variation: Firefox (sandboxed), KeePassXC (host-installed)
  3. Exposing the UNUX socket from the KeePassXC flatpak to other applications outside of the Flatpak. (solution: an symbolic link)

Current workaround

v1.1

Tested with: Fedora 32, org.mozilla.firefox v75 from flathub, org.keepassxc.KeePassXC v2.5.4 from flathub

Starting keepassxc-proxy by Firefox

  1. Worst things first: We need the keepassxc-proxy as a binary, because we want to have it run inside of the Firefox flatpak. Good for us: it has not many depenencies and is available as a stand-alone application.
    1. So I chose the Rust proxy application (because why should not I? :upside_down_face:). If you trust me, you can get my compiled binary below, just skip to two steps ahead.
    2. Clone the git repo and compile it (run cargo build --release).
    3. You find the result in ./target/release.
      The keepassxc-proxy binary, version 211ae91, compiled with rustc 1.43.0 (the current stable in Fedora 32) for x86_64 (and if it helps and you wanna know more that .rustc_info.json).
      And altghough Rust is not (yet) totally reproducibly compiling I did got the same bit-by-bit result on two machines with Fedora 32. The SHA-256 hash is c5c4c6c011a4d64f7e4dd6c444dcc70bee74d23ffb28c9b65f7ff6d89a8f86ea.
      So if you are in a risky mood, you can just download my keepassxc-proxy binary here. (hosted by GitHub :stuck_out_tongue_winking_eye:)
  2. Now we need to tell Firefox about the new binary.
    1. Go to ~/.var/app/org.mozilla.firefox/.mozilla/native-messaging-hosts. Actually, the native-messaging-hosts likely does not exist yet, so do create it.
    2. Create a file org.keepassxc.keepassxc_browser.json in there, and paste in the following content:
      {
          "allowed_extensions": [
              "keepassxc-browser@keepassxc.org"
          ],
          "description": "KeePassXC integration with native messaging support, workaround for flatpaked Firefox, see https://is.gd/flatpakFirefoxKPXC",
          "name": "org.keepassxc.keepassxc_browser",
          "path": "/home/REPLACE_WITH_USERNAME/.var/app/org.mozilla.firefox/.mozilla/native-messaging-hosts/keepassxc-proxy",
          "type": "stdio"
      }
      
      Note that only absolute paths work (I guess), so replace REPLACE_WITH_USERNAME with your $USER name, so that the paths leads to it’s own working dir.
    3. You see what I am doing: We now place the downloaded/compiled keepassxc-proxy in the same dir. Obviously, you could use any other path there, but this was the first one that is obviously accessible by Firefox and you have everything in one place. (If you have better suggestions, feel free to let me know.)
      Note: Remember to make it executable (chmod +x) if it is not, already.

Allowing Firefox to access the socket

KeePassXC, by default, creates it’s socket in $XDG_RUNTIME_DIR/kpxc_server. So this is what we need to give the Firefox flatpak access to (read-only is obviously enough).

Fortunately, this is easy. Just run:

$ sudo flatpak override --filesystem=xdg-run/kpxc_server:ro org.mozilla.firefox

Hooray!: For those, who install KeePassXC on the host (without any sandbox/flatpak), this is enough. Start KeePassXC and then Firefox and it should be able to connect. :tada:
Please note the “existing problems” section at the bottom, though.

Continue, if you also want to run KeePassXC in a flatpak.

Exposing the UNIX socket from the KeePassXC flatpak

Note: Again skip to the bullet point (point 1) below, if you don’t wanna know the technical background.

The flatpaked KeePassXC from Flathub creates it’s Unix socket in the location flatpaks should do so, in $XDG_RUNTIME_DIR/app/org.keepassxc.KeePassXC/kpxc_server. (If it would use $XDG_RUNTIME_DIR directly like the “native” KeePassXC, it would only exist in the sandbox.)

As we know, the usual keepassxc-proxy expects the file at $XDG_RUNTIME_DIR/kpxc_server. To solve this, we just create a symbolic link.
As you can verify, this actually solves our problem. For some very strange reason, the Flatpak sandbox now allows Firefox (and all other flatpaks! Just FYI, be aware of that.) to see that UNIX socket file.
As it should turn out later, this does not work when you move that symbolic link anywhere else (even another file name already prevents it from working – I’ve tried a lot of things.).

However, $XDG_RUNTIME_DIR is usually deleted at shutdown. So we need to recreate it at startup/user login. Good for us there, is already a tool for that. (you could also mangle with shell scripts in your autostart of course, but that is ugly.)
That’s why we make use of systemd-tmpfiles. (The man page for tmpfiles.d is more useful for us actually.)

  1. Go to ~/.local/share/user-tmpfiles.d. Again, there is a high chance the user-tmpfiles.d dir does not exist yet. If so… well… you know what to do…
  2. Now download and place the following config file in there: kpxc_server.conf
    This is basically a config file for systemd-tmpfiles that says it to create that symbolic link for the user.
  3. Reboot, so systemd-tmpfiles can apply the changes and create the config file.

Hooray!: Afterwards start the KeePassXC flatpak and then Firefox and it should be able to connect. :tada:

Please note the “existing problems” section below.

Existing problems

  • Firefox, for some reason, cannot see the $XDG_RUNTIME_DIR/kpxc_server file, if the file (respectively it’s symbolic link target) does not exist yet.
    In practise, this results in one big disadvantage: You always need to start KeePassXC before Firefox.
  • For some more strange reason, if you have this workaround setup, the usual way that you run a non-flatpaked native Firefox and connect it by spawning the proxy inside the flatpak (like flatpak run org.keepassxc.KeePassXC) may not work. Delete the symbolic link again to make this work.

Debugging tips

  • In Firefox use about:debugging to access add-on internals. keepassxc-browser@keepassxc.org is the add-on ID. It actually also logs failed attempts. Note there are different results (logs and visibly) when it cannot start the proxy vs when it can start the proxy, but no connection suceeds (because the UNIX socket is not there, e.g.)
  • To manually get into the flatpak and “see” in a shell what it has access to/looks like, use something like flatpak run --command=/bin/sh org.mozilla.firefox.
  • To check whether the socket file is accessible (a symbolic link can point to a non-existant file) just cat it and you’ll see a strange error that cat cannot find a resource

Things I’ve tried

Things that do not work:
Preserved for future solutions and better™ workarounds.

  • all things in $XDG_RUNTIME_DIR/app are highly sandboxed, even with flatpak overrides I could not get the Firefox flatpak to read the content of the ../org.keepassxc.KeePassXC dir. Even with crazy symbolic links in it’s own dir. (Do try it though, maybe you’ll make it! At least you’ll learn something. :wink:.)
  • what works though is: You can override the KeePassXC flatpak to get access to Mozilla. Only write access possible though! Thus, if it would place the proxy there (again: symbolic links here don’t work!), Firefox could also read it.
  • The symbolic link must be created by an application outside of the sandbox. Inside of it, it’s again – sandboxed – and one only visible inside of it.

Final notes

If this helped, feel free to leave me a :heart: for this post and/or upvote it on Unix Stackexchange. It took quite some time to figure it out.

I do try to continue improving this workaround and find solutions in this GitHub issue. It’s best to follow there, if you are interested.


I’ve cross-posted this question and answer on Unix Stackexchange and in the Fedora community.

4 Likes

I haven’t had a chance to digest all of this yet, but besides all the GitHub links it is probably worth referencing this ticket in Mozilla’s bug tracker for the Firefox Flatpak regarding support for KeePassXC and other extensions that use native messaging. Also, perhaps you want to provide a reference for your solution on that ticket.

1 Like

Thanks! I had to apply one change as the keepassxc server socket has a different name now:
$XDG_RUNTIME_DIR/app/org.keepassxc.KeePassXC/org.keepassxc.KeePassXC.BrowserServer
Therefore my ~/.local/share/user-tmpfiles.d/kpxc_server.conf now goes
L %t/kpxc_server - - - - %t/app/org.keepassxc.KeePassXC/org.keepassxc.KeePassXC.BrowserServer

Also, there is no need to reboot, just run
systemd-tmpfiles --user --create

P.S.: After a few tests, I have to say that this doesn’t work reliably. Keepassxc and firefox seem to be connected, but in most instances, keepassxc-browser says “no entries found”.

After playing around with it a bit, I have to report that it kind of works on one of my machines, but on two others, it doesn’t. KeePassXC-browser connects to keepassxc, and the icon changes, but then it immediately looses connection again and reports that key exchange has failed. I know too little about the firefox debugger to understand how to debug this problem