Permissions
If you have hyprland-guiutils installed, you can make use of Hyprland’s built-in permission system.
For now, it only has a few permissions, but it might include more in the future.
Tip
If you care about this permissions system, you probably also care about blocking access to Hyprland’s IPC sockets. Hyprland itself cannot enforce this; consult the documentation for your application sandbox of choice.
Permissions
Permissions work a bit like Android ones. If an app tries to do something sensitive with the compositor (Hyprland), Hyprland will pop up a notification asking you if you want to let it do that.
Note
Before setting up permissions, make sure you enable them by setting hl.config({ ecosystem = { enforce_permissions = true } }), as it’s disabled by default.
Configuring permissions
Important
Permissions set up in the config are not reloaded on-the-fly and require a Hyprland restart for security reasons.
Configuring them is simple:
hl.permission({ binary, type, mode })For example:
hl.permission({ binary = "/usr/bin/grim", type = "screencopy", mode = "allow" })will allow /usr/bin/grim to always capture your screen without asking, and
hl.permission({ binary = "/usr/bin/appsuite-.*", type = "screencopy", mode = "allow" })will allow any app whose path starts with /usr/bin/appsuite- to capture your screen without asking.
Permission modes
There are 3 modes:
allow: Don’t ask, just allow the app to proceed.ask: Pop up a notification every time the app tries to do something sensitive. These popups let you Deny, Allow until the app exits, or Allow until Hyprland exits.deny: Don’t ask, always deny the application access.
Permission list
screencopy
- Default: ASK
- Access to your screen without going through xdg-desktop-portal-hyprland. Examples include:
grim,wl-screenrec,wf-recorder. - If denied, will render a black screen with a “permission denied” text.
- Why deny? For apps/scripts that might maliciously try to capture your screen without your knowledge by using Wayland protocols directly.
plugin
- Default: ASK
- Access to load a plugin. Can be either a regex for the app binary, or plugin path.
- Do not allow
hyprctlto load your plugins by default (attacker could issuehyprctl plugin load /tmp/my-malicious-plugin.so) - use eitherdenyto disable oraskto be prompted.
keyboard
- Default: ALLOW
- Access to connecting a new keyboard. Regex of the device name.
- If you want to disable all keyboards not matching a regex, make a rule that sets
DENYfor.*as the last keyboard permission rule. - Why deny? Rubber duckies, malicious virtual/USB keyboards.
cursorpos
- Default: ASK
- Access to your cursor position and cursor image via Wayland protocols directly.
- Why deny? Prevents apps from silently tracking where your cursor is without going through xdg-desktop-portal.
input-capture
- Default: ASK
- Access to capture all input events from the compositor (keyboard, pointer, touch).
- Why deny? Prevents apps from maliciously capturing all user input without your consent.
Notes
Portals
xdg-desktop-portal implementations (including XDPH) are just regular applications. They will go through permissions too. You might want to consider adding a rule like this:
hl.permission({ binary = "/usr/(lib|libexec|lib64)/xdg-desktop-portal-hyprland", type = "screencopy", mode = "allow" })if you are not allowing screencopy for all apps.
NixOS
NixOS does not have static paths for the binaries, so regex must be used.
These example rules allow grim and xdg-desktop-portal-hyprland to copy the screen:
hl.permission({ binary = "/nix/store/[a-z0-9]{32}-grim-[0-9.]*/bin/grim", type = "screencopy", mode = "allow" })
hl.permission({ binary = "/nix/store/[a-z0-9]{32}-xdg-desktop-portal-hyprland-[0-9.]*/libexec/.xdg-desktop-portal-hyprland-wrapped", type = "screencopy", mode = "allow" })When rendering the configuration with Nix itself, string interpolation can also be used.
Be aware that if the path contains special regex characters (e.g. +) they need to be escaped:
hl.permission({ binary = "${lib.getExe pkgs.grim}", type = "screencopy", mode = "allow" })
hl.permission({ binary = [[${lib.escapeRegex (lib.getExe config.programs.hyprlock.package)}]], type = "screencopy", mode = "allow" })
hl.permission({ binary = [[${pkgs.xdg-desktop-portal-hyprland}/libexec/\.xdg-desktop-portal-hyprland-wrapped]], type = "screencopy", mode = "allow" })BSD
On some BSD systems paths might not work. In such cases, you might want to disable permissions altogether, by setting:
hl.config({
ecosystem = {
enforce_permissions = false
}
})Otherwise, you will have no config control over permissions (popups will still work, although they will not show paths, and “remember” will not be available).