So after many test and reading documentation about the syntax for apparmor i finally create some apparmor profiles specially for Qubes.
The goal of this post is to increase the security of a normal user without affecting his experience this the number #1 priority
For now there is only two profiles but i’m planning to add other profiles such as Brave,Librewolf,Mullvad-Browser,Network-Manager (for sys-net) and more !
- Start your debian template
- I recommend to use the kicksecure repository to get their apparmor package
- Do
echo "Types: deb
URIs: https://deb.kicksecure.com
Suites: trixie
Components: main contrib non-free
Enabled: yes
Signed-By: /usr/share/keyrings/derivative.asc" | sudo tee /etc/apt/sources.list.d/derivative.sources
Or if you prefer to use their tor repository you can do
echo "Types: deb
URIs: tor+https://deb.kicksecure.com
Suites: trixie
Components: main contrib non-free
Enabled: yes
Signed-By: /usr/share/keyrings/derivative.asc" | sudo tee /etc/apt/sources.list.d/derivative.sources
You could use their onion repository here but updating packages in the future will be very slow.
By using the tor repository you will need sys-whonix or the tor package installed in your system to install their packages.
- Then open your terminal and install those packages in the debian template run
sudo apt-get -y install apparmor apparmor-utils apparmor-profiles apparmor-profiles-extra apparmor-profiles-kicksecure
- Shutdown the template
In order to make apparmor works correctly in Qubes you need to run this commands in dom0 :
qvm-prefs x kernelopts "swiotlb=2048 security=apparmor"
Replace “x” by the name of your template
- Start your templateVM open a terminal and confirm apparmor is running by doing as root
sudo aa-enabled
It must say “Yes” in that case you can continue the guide otherwise you have done something wrong.
- As root run this command to install the firefox apparmor profile
echo "abi <abi/4.0>,
include <tunables/global>
# This profile allows everything and only exists to give the
# application a name instead of having the label "unconfined"
profile firefox /{usr/lib/firefox{,-esr,-beta,-devedition,-nightly},opt/firefox}/firefox{,-esr,-bin} {
include <abstractions/audio>
include <abstractions/totem>
include if exists <local/firefox>
capability sys_admin,
capability sys_chroot,
capability sys_ptrace,
deny / r,
deny /home/user/Desktop**/ r,
deny /home/user/Documents**/ r,
deny /home/user/Pictures**/ r,
deny /home/user/QubesIncoming**/ r,
deny /home/user/Templates**/ r,
deny /home/user/Videos**/ r,
deny /home/user/Music**/ r,
deny owner /home/*/.bash_logout r,
deny owner /home/*/.bashrc r,
deny owner /home/user/.profile r,
deny owner /home/user/.xsession-errors r,
/dev/udmabuf rw,
/etc/dconf/db/local r,
/etc/dconf/profile/user r,
/etc/firefox/policies/policies.json r,
/etc/ld.so.cache r,
/etc/ld.so.preload r,
/etc/mime.types r,
/proc/pressure/memory r,
/sys/devices/system/cpu/* r,
/sys/devices/system/cpu/** r,
/sys/fs/cgroup/user.slice/user-1000.slice/** r,
/usr/bin/update-desktop-database mrix,
/usr/bin/update-mime-database mrix,
/usr/lib/firefox/crashhelper mrix,
/usr/lib/firefox/firefox-bin mrix,
/usr/lib/firefox/glxtest mrix,
/var/cache/fontconfig/ rw,
owner /home/user/.cache/mesa_shader_cache/* rw,
owner /home/user/.cache/mesa_shader_cache/** r,
owner /home/user/.cache/mesa_shader_cache/** w,
owner /home/user/.cache/mozilla/ rw,
owner /home/user/.cache/mozilla/*/ rw,
owner /home/user/.cache/mozilla/firefox/** k,
owner /home/user/.cache/mozilla/firefox/** r,
owner /home/user/.cache/mozilla/firefox/** w,
owner /home/user/.cache/mozilla/firefox/*/ rw,
owner /home/user/.config/* r,
owner /home/user/.config/* w,
owner /home/user/.config/dconf/* r,
owner /home/user/.config/mozilla/ rw,
owner /home/user/.config/mozilla/** k,
owner /home/user/.config/mozilla/** r,
owner /home/user/.config/mozilla/** w,
owner /home/user/.config/pulse/ rw,
owner /home/user/.local/share/applications/ rw,
owner /home/user/.local/share/applications/* w,
owner /home/user/.local/share/mime/ rw,
owner /home/user/.local/share/mime/packages/ rw,
owner /home/user/.local/share/mime/packages/* w,
owner /home/user/.zcompdump r,
owner /home/user/Downloads/* r,
owner /home/user/Downloads/* w,
owner /proc/*/* w,
owner /proc/*/cgroup r,
owner /proc/*/cmdline r,
owner /proc/*/stat r,
owner /proc/*/task/** r,
owner /run/user/1000/dconf/* rw,
owner /run/user/1000/pulse/ rw,
userns,
} " | sudo tee /etc/apparmor.d/firefox
- For Nautilus (file manager) do
echo "include <tunables/global>
profile nautilus /usr/bin/nautilus {
include <abstractions/gio-open>
include <abstractions/hosts_access>
include <abstractions/nvidia>
include <abstractions/totem>
include if exists <local/nautilus>
deny /*/ r,
deny owner /home/user/.xsession-errors r,
/dev/udmabuf rw,
/etc/dconf/db/local r,
/etc/dconf/profile/user r,
/home/user/firefox rw,
/sys/devices/system/cpu/** r,
/usr/bin/qvm-open-in-vm Ux,
/usr/bin/x86_64-linux-gnu-cpp-14 r,
/usr/lib/qubes/qvm-copy-to-vm.gnome Ux,
owner /home/** rw,
owner /home/*/.bash_logout r,
owner /home/*/.bashrc r,
owner /home/*/.config/gtk-3.0/bookmarks w,
owner /home/*/.config/gtk-4.0/* r,
owner /home/*/.local/share/Trash/files/ rw,
owner /home/*/.local/share/Trash/info/ rw,
owner /home/*/.profile r,
owner /home/*/Desktop/Documents/ rw,
owner /home/*/Documents/Music/ rw,
owner /home/*/Music/Videos/ rw,
owner /home/user/.cache/mesa_shader_cache/** k,
owner /home/user/.cache/mesa_shader_cache/** r,
owner /home/user/.cache/mesa_shader_cache/** w,
owner /home/user/.cache/mesa_shader_cache/*/ w,
owner /home/user/.config/dconf/* r,
owner /home/user/.local/share/Trash/ rw,
owner /home/user/.local/share/nautilus/** k,
owner /home/user/.local/share/nautilus/** rw,
owner /home/user/.zcompdump r,
owner /home/user/Documents/ rw,
owner /home/user/Downloads/ r,
owner /run/user/1000/dconf/* r,
owner /run/user/1000/dconf/* w,
owner /usr/share/nautilus-python/**/ rw,
userns,
} " | sudo tee /etc/apparmor.d/nautilus
- Then run
sudo aa-enforce /etc/apparmor.d/nautilus && sudo aa-enforce /etc/apparmor.d/firefox
- If a error appear about a protocol you can ignore this error i don’t know why exactly it happen but run the 9 commands again until it stop complaining i had to run it 2 or 3 times to work
- It’s done now firefox and nautilus is running under apparmor with strict permissions
F.A.Q
“Do Qubes copy-vm menu entry works ?”
Yes i’ve tried and it works without any issue
“Can i use firejail with your profiles ?”
You shouldn’t do it in fact using firejail will only increase the possibility of an attack the creator of Firejail has said himself this
Don't use this on enterprise servers, or any other multiuser system. Firejail was built for single-user desktops.
Maybe you could use firejail with my apparmor profiles but i didn’t test to see if it works and i will never do it because i’ve tested firejail for a long time with Qubes and some applications wasn’t properly starting with firejail so it was running without any protection which make firejail useless for example Nautilus wasn’t launching with firejail so i have to find a trick to force Nautilus to run under firejail which is frustrating to do. There is a good reason why Tails , Whonix or Secureblue do not rely on firejail to secure a system they rely only on Apparmor or Selinux or Secureblue.
“What’s the main advantage of using those apparmor profiles ?”
They increase the security of your system and reduce the possibility of an attack a lot more
For example Firefox can’t access to the root filsystem , Firefox can’t access the folder “QubesIncoming” (I’m not sure if a website can still see if the folder is present with javascript or something else i need a expert to tell me)
The only folder firefox can access is the Downloads folder.
Nautilus do not have internet access and can’t access to the root filesystem nautilus can only access to all folder inside the home directory.
The apparmor profile for Firefox and Nautilus is maybe not perfect if this is the case just tell me i will try my best to fix everything.
I think i will create a github repo in the future for the future apparmor profiles and maintain those profiles as long QubesOS survive. The next profile i’m planning to add will be Network-Manager and Brave and Thunar. But first i need to see if people have some issue with the firefox and nautilus profile.
Edit : Just to make sure your appvm and dispvm is really using apparmor go to the settings of both vm and click on “Services” then select “apparmor” and click on “apply”. It might be possible the apparmor service doesn’t appear in the list of Services in that case click on “(custom…)” and click on “Add” then type “apparmor” and apply.
Edit 2 : Added a explanation to tell the users to not use firejail
Edit 3 : I removed the “deny network” rule it make nautilus doesn’t work at all i will find a another way