Classic confinement request for MenuLibre

To make the review of your request easier, please use the following template to provide all the required details and also include any other information that may be relevant.


  • name: MenuLibre
  • description: MenuLibre is a gtk app to easily edit user and system .desktop files displayed in the gnome menu.
  • snapcraft: The snapcraft.yaml
  • upstream: github repo of MenuLibre
  • upstream-relation: Merely a user of the app that would like to have it as a snap.
  • supported-category: as I understand it : tools for local, non-root user driven configuration of/switching to development workspaces/environments
  • reasoning: MenuLibre needs to have access to the system’s $PATH to work, as it displays and edits the system’s .desktop files. I have found in this forum topic that there is no way to grant a snap access to the host’s $PATH, and I therefore think the classic confinement is the only solution in order to have MenuLibre working as a snap. Furthermore, MenuLibre is already well known and open-source.

I understand that strict confinement is generally preferred over classic.

I’ve tried the existing interfaces to make the snap to work under strict confinement.

Note that snappy-debug can be used to identify possible required interfaces. See https://snapcraft.io/docs/debug-snaps for more information.

So that the snap can still be strictly confined, could the system-files interface be used instead to allow access to certain files/dirs?

Maybe, my technical knwoledge is quite limited and any clue is appreciated. From what I’ve read and tried though, a system-files access to /usr/share doesn’t work, nor do layouts for that matter.

A hook to create symbolic links between /usr/share/applications and $SNAP/usr/share/applications coudn’t be done as the files in /usr/share/applications were “read-only”

Adding /var/lib/snapd/hostfs/usr/share and so on to the XDG_DATA_DIRS variable does allow to show the apps and icons in the snap, but not to modify them.

Here is the strict snapcraft.yaml that doesn’t work :

name: menulibre
base: core24 # the base snap is the execution environment for this snap
version: '1.0' # just for humans, typically '1.2+git' or '1.3.2'
summary: MenuLibre is an advanced FreeDesktop.org compliant menu editor.
description: |
  MenuLibre is an advanced menu editor with modern features in a clean, easy-to-use interface. It lets you :
    --> Create new launchers or modify existing ones with complete control and access to hidden settings
    --> Add and adjust desktop actions: shortcuts to advanced application features
    --> Easily rearrange the menu to suit your tastes
grade: stable # must be 'stable' to release into candidate/stable channels
confinement: devmode # use 'strict' once you have the right plugs and slots

layout:
  /usr/share/lib/X11:
    symlink: $SNAP/usr/share/lib/X11
  /usr/lib/x86_64-linux-gnu/libgtk-3-0: 
    bind: $SNAP/usr/lib/x86_64-linux-gnu/libgtk-3-0t64
  /usr/share/applications:
    bind: $SNAP/usr/share/applications
  /usr/share/icons:
    bind: $SNAP/usr/share/icons

plugs:
  applications:
    interface: system-files
    write: [/home/$USER/.local/share/applications]
  icons:
    interface: system-files
    write: [/home/$USER/.local/share/icons]
  system-applications: 
    interface: system-files
    write: [/usr/share/applications]
  system-icons:
    interface: system-files
    write: [/usr/share/icons]
  #path:
  #  interface: system-files
  #  read: [/usr/bin]

apps:
  menulibre:
    environment:
      PYTHONPATH: $SNAP/usr/lib/python3/dist-packages:$PYTHONPATH
      GI_TYPELIB_PATH: $SNAP/usr/lib/x86_64-linux-gnu/girepository-1.0
      GTK_IM_MODULE_FILE: /usr/lib/x86_64-linux-gnu/libgtk-3-0/gtk-query-immodules-3.0
      PATH: /var/lib/snapd/hostfs/usr/bin:$PATH
      XDG_DATA_DIRS: /var/lib/snapd/hostfs/usr/share:/var/lib/snapd/hostfs/usr/local/share:/home/$USER/.local/share:/home/$USER/.local/share/flatpak/exports/share:/var/lib/snapd/hostfs/var/lib/flatpak/exports/share:/var/lib/snapd/hostfs/usr/share/ubuntu:/var/lib/snapd/hostfs/usr/share/gnome:$XDG_DATA_DIRS
    command: bin/menulibre
    command-chain: [bin/desktop-launch]
    plugs:
      - home
      - x11
      - wayland

#hooks:
#  configure:
#   plugs:
#     - applications
#     - icons
#     - system-applications
#     - system-icons
      
parts:
  desktop-gtk3:
    source: https://github.com/ubuntu/snapcraft-desktop-helpers.git
    source-subdir: gtk
    plugin: make
    make-parameters: ["FLAVOR=gtk3"]
    build-packages:
      - build-essential
      - libgtk-3-dev
    stage-packages:
      - libxkbcommon0  # XKB_CONFIG_ROOT
      - fonts-ubuntu
      - dmz-cursor-theme
      - light-themes
      - adwaita-icon-theme
      - gnome-themes-extra
      - shared-mime-info
      - libgtk-3-0
      - libgdk-pixbuf2.0-0
      - libglib2.0-bin
      - libgtk-3-bin
      - unity-gtk3-module
      - libappindicator3-1
      - locales-all
      - xdg-user-dirs
      - ibus-gtk3
      - libibus-1.0-5
      - fcitx-frontend-gtk3
      - xkb-data
  menulibre:
    plugin: python
    source: https://github.com/bluesabre/menulibre.git
    build-packages:
      - gir1.2-gtk-3.0
      - intltool
      - libgnome-menu-3-dev
      - python-gi-dev
      - python3
      - python3-distutils-extra
      - python3-psutil
    stage-packages:
      - gir1.2-gdkpixbuf-2.0
      - gir1.2-glib-2.0
      - gir1.2-gmenu-3.0
      - gir1.2-gtk-3.0
      - gir1.2-gtksource-3.0
      - gobject-introspection
      - gnome-menus
      - python3
      - python3-gi
      - python3-psutil
      - xdg-utils

    override-build: |
      python3 setup.py build
      mkdir -p $SNAPCRAFT_PART_INSTALL/bin
      cp -r /root/parts/menulibre/build/bin/* $SNAPCRAFT_PART_INSTALL/bin/
      cp -r /root/parts/menulibre/build/* $SNAPCRAFT_PART_INSTALL/

Once again, maybe there’s a way but I just don’t know it / didn’t find anything hitting it on this forum, and if so I apologize.

Layouts are not designed for something like this, their purpose is to show an application directories in a way the app expects them, but they always point somewhere into your snap space, not outside of it…

The system-files interface though is designed for exactly this use case and is used by a lot of snaps to access system directories including stuff under /usr/share

Note though … looking at your snapcraft.yaml above you can not use system-files for anything under $HOME, for that you need to use the personal-files interface

When you add such an interface you also need to manually connect it using the snap connect ... command, these privileged interfaces do not auto-connect by default …

Thanks for the personal-files info. But I really don’t understand how it “exposes” the host’s files. Because I did try to add the right system-files plugs, but when searching within the snap environment it just doesn’t change anything.

For instance here is what I get inside the snap environement :

loic@Ubuntu:~/Documents/Snapcraft/menulibre$ snap connect menulibre:applications ; snap connect menulibre:icons ; snap connect menulibre:system-applications ; snap connect menulibre:system-icons
loic@Ubuntu:~/Documents/Snapcraft/menulibre$ snap run --shell menulibre
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

loic@Ubuntu:/home/loic/Documents/Snapcraft/menulibre$ ls /usr/share/applications/
mimeapps.list  python3.12.desktop  vim.desktop	xdg-open.desktop
loic@Ubuntu:/home/loic/Documents/Snapcraft/menulibre$ ls ~/.local/share/applications/
appimagekit_3c274332152706b8c487d142d7071a8e-Beeper.desktop  org.gnome.clocks.desktop

This is absolutely not the files that are on my host’s applications and icons folder. To find those, I need to go to /home/$USER/.local/share/applications and /var/lib/snapd/hostfs/usr/share/applications. But both these locations are accessible from within the snap when the personal-files and system-files interfaces are not connected.

What am I missing here ? Why the plugs expose the directories to my snap ? It’s honestly kinda driving me crazy, 'cause I feel like I’m missing something really obvious haha :sweat_smile:

Here is the snapcraft.yaml used for the outputs showed earlier.

name: menulibre
base: core24 # the base snap is the execution environment for this snap
version: '1.0' # just for humans, typically '1.2+git' or '1.3.2'
summary: MenuLibre is an advanced FreeDesktop.org compliant menu editor.
description: |
  MenuLibre is an advanced menu editor with modern features in a clean, easy-to-use interface. It lets you :
    --> Create new launchers or modify existing ones with complete control and access to hidden settings
    --> Add and adjust desktop actions: shortcuts to advanced application features
    --> Easily rearrange the menu to suit your tastes
grade: stable # must be 'stable' to release into candidate/stable channels
confinement: devmode # use 'strict' once you have the right plugs and slots

layout:
  /usr/share/lib/X11:
    symlink: $SNAP/usr/share/lib/X11
  /usr/lib/x86_64-linux-gnu/libgtk-3-0: 
    bind: $SNAP/usr/lib/x86_64-linux-gnu/libgtk-3-0t64

plugs:
  applications:
    interface: personal-files
    write: [$HOME/.local/share/applications]
  icons:
    interface: personal-files
    write: [$HOME/.local/share/icons]
  system-applications: 
    interface: system-files
    write: [/usr/share/applications]
  system-icons:
    interface: system-files
    write: [/usr/share/icons]

apps:
  menulibre:
    environment:
      PYTHONPATH: $SNAP/usr/lib/python3/dist-packages:$PYTHONPATH
      GI_TYPELIB_PATH: $SNAP/usr/lib/x86_64-linux-gnu/girepository-1.0
      GTK_IM_MODULE_FILE: /usr/lib/x86_64-linux-gnu/libgtk-3-0/gtk-query-immodules-3.0
      PATH: /var/lib/snapd/hostfs/usr/bin:$PATH
    command: bin/menulibre
    command-chain: [bin/desktop-launch]
    plugs:
      - home
      - x11
      - wayland
      - applications
      - icons
      - system-applications
      - system-icons
      
parts:
  desktop-gtk3:
    source: https://github.com/ubuntu/snapcraft-desktop-helpers.git
    source-subdir: gtk
    plugin: make
    make-parameters: ["FLAVOR=gtk3"]
    build-packages:
      - build-essential
      - libgtk-3-dev
    stage-packages:
      - libxkbcommon0
      - fonts-ubuntu
      - dmz-cursor-theme
      - light-themes
      - adwaita-icon-theme
      - gnome-themes-extra
      - shared-mime-info
      - libgtk-3-0
      - libgdk-pixbuf2.0-0
      - libglib2.0-bin
      - libgtk-3-bin
      - unity-gtk3-module
      - libappindicator3-1
      - locales-all
      - xdg-user-dirs
      - ibus-gtk3
      - libibus-1.0-5
      - fcitx-frontend-gtk3
      - xkb-data
  menulibre:
    plugin: python
    source: https://github.com/bluesabre/menulibre.git
    build-packages:
      - gir1.2-gtk-3.0
      - intltool
      - libgnome-menu-3-dev
      - python-gi-dev
      - python3
      - python3-distutils-extra
      - python3-psutil
    stage-packages:
      - gir1.2-gdkpixbuf-2.0
      - gir1.2-glib-2.0
      - gir1.2-gmenu-3.0
      - gir1.2-gtk-3.0
      - gir1.2-gtksource-3.0
      - gobject-introspection
      - gnome-menus
      - python3
      - python3-gi
      - python3-psutil
      - xdg-utils

    override-build: |
      python3 setup.py build
      mkdir -p $SNAPCRAFT_PART_INSTALL/bin
      cp -r /root/parts/menulibre/build/bin/* $SNAPCRAFT_PART_INSTALL/bin/
      cp -r /root/parts/menulibre/build/* $SNAPCRAFT_PART_INSTALL/

This request is quite tricky I think. Allowing write access to ~/.local/share/applications allows a trivial sandbox escape for this snap since it can just drop a new desktop file there that overrides the one installed by snapd which launches itself (or some other application) outside of the regular confinement provided by snapd.

On the other hand, I don’t see this snap fitting on any of the existent categories for classic either.

@alexmurray @pedronis any suggestion?

Hey again,

As I said, both classic and write access to ~/.local/share/applications are super privileged. This kind of super privileged operations are reserved for the upstream after publisher vetting. Thus, considering you are not part of the upstream project (as indicated in the upstream-relation) , I think we cannot continue with this request.

Best alternatives to continue with the request could be either you engage the upstream, or the upstream takes over the snap publication if they are interested

Thanks for your interest and sorry for the delay