Android-like privacy & permission manager for Linux
PermGuard watches your system in real-time. The moment an unknown app tries to use your camera, microphone, files, or install software, it is immediately frozen and a popup asks you what to do β just like on Android. You choose, PermGuard remembers. Your rules survive reboots.
git clone https://github.com/Ahmedouyahya/PermGuard.git && cd PermGuard && bash install.shThe installer detects your distro (Debian/Ubuntu, Fedora, Arch, openSUSE), installs all dependencies, and sets up a systemd user service so PermGuard starts automatically at every login.
permguard # launch manually
python -m permguard # equivalent β useful when the wrapper isn't on PATH
permguard --versionUpdate to latest version:
bash install.sh # always pulls from GitHub firstUninstall:
bash install.sh --uninstallWhen an unknown app accesses a protected resource:
App opens /dev/video0 βββΆ CameraMonitor detects it
β
SIGSTOP (freeze app)
β
ββββββββββΌβββββββββ
β π· Firefox β
β wants your β
β camera β
β Frozen... β
β β
β [Allow] β
β [Allow once] β
β [Deny] β
βββββββββββββββββββ
β
ββββββββββββββββββΌβββββββββββββββββββ
βΌ βΌ βΌ
Allow Allow once Deny
SIGCONT SIGCONT SIGKILL
(save rule) (no rule) (save rule)
The app is completely frozen while you decide β it cannot read a single frame, audio sample, or file byte until you respond. If you don't respond within 30 seconds, access is automatically denied.
| Tab | What it does |
|---|---|
| π Dashboard | Live overview of all categories + one-click camera/mic block |
| π· Camera | Apps currently accessing the webcam, kill button |
| π€ Mic | Apps capturing audio via PipeWire/PulseAudio, kill button |
| π₯ Screen | Active screen recording/sharing sessions |
| π Network | All active TCP/UDP connections per process, block button |
| π USB | Connected USB devices with enable/disable control |
| π Ports | Listening ports and owning processes |
| βοΈ Processes | Top processes by CPU, kill button |
| π₯ Firewall | Active network blocks per app (iptables) |
| π Files | Protected directories β add paths, view access events |
| π Permissions | All saved allow/deny rules for camera, mic, screen, filesystem, and package installs β add rules manually, revoke any |
| β Settings | Autostart, refresh interval, event log |
- Camera & Mic β detected via
/proc/<pid>/fdsymlinks andpactl. Frozen with SIGSTOP, resumed with SIGCONT or killed with SIGKILL. - File access β inotify watches on protected directories (
~/.ssh,~/.gnupg,~/.config/permguardby default, user-configurable). Access detected via/procfd scan. - Package installs β
/procpolled every 2s forapt,pip,npm,snap,flatpak,pacman,dnf,cargo, and 15+ other package managers. - Network blocking β
iptables OUTPUTrules keyed by UID. Persisted across reboots. - USB control β reads/writes
/sys/bus/usb/devices/<id>/authorizedvia pkexec.
All decisions survive reboots:
| File | What's stored |
|---|---|
~/.local/share/permguard/permissions.json |
Per-app allow/deny rules + notification/interval settings |
~/.local/share/permguard/firewall_rules.json |
Network blocks (re-applied at startup, de-duplicated against live iptables) |
~/.local/share/permguard/device_state.json |
Camera/mic block state (re-applied at startup) |
~/.local/share/permguard/timeline.json |
Last 7 days of access events (shown on the Dashboard tab) |
~/.local/share/permguard/events.log |
Full audit log (rotated at 5000 lines) |
Every state file is written atomically (temp file + os.replace) with 0o600 permissions, and the data directory itself is 0o700 β no other user on the machine can read your rules, log, or timeline.
- Zombie-proof dialogs β if an app exits while its permission prompt is still on screen, PermGuard dismisses the stale dialog and thaws the frozen process automatically instead of leaving an orphaned popup.
- Self-exclusion β the file monitor skips its own PID and child processes so PermGuard can never freeze itself while reading its own config.
- Firewall idempotency β on restart, existing
iptablesDROP rules are detected withiptables -Cand skipped, so restarting the service can no longer pile up duplicate rules. - Shell-injection safe β privileged writes to sysfs (
/sys/bus/usb/.../authorized) go throughpkexec teewith the value on stdin; no untrusted device ID ever touches a shell. - Thread-safe timeline β concurrent monitor threads write to the event timeline through an in-memory cache guarded by a lock, so events from simultaneous camera/mic/file accesses can't clobber each other.
PermGuard runs as a proper systemd user service:
systemctl --user status permguard
systemctl --user stop permguard
systemctl --user restart permguardPermGuard is designed to consume as close to zero resources as possible when nothing is happening.
The camera monitor uses the Linux inotify kernel API instead of polling. It registers IN_OPEN watches on /dev/video* devices and blocks in select() until the kernel wakes it up β literally 0% CPU when no camera is in use. When a device is opened, it wakes up in under a millisecond, scans /proc/<pid>/fd to identify the process, and goes back to sleep.
Earlier versions spawned subprocesses for every data query. These were replaced with direct reads from Linux kernel interfaces:
| Data | Old method | New method | Latency |
|---|---|---|---|
| Camera PIDs | fuser /dev/video* |
/proc/<pid>/fd symlink scan |
57ms β 9ms |
| Network connections | ss -tunp |
/proc/net/tcp + /proc/net/tcp6 |
18ms β 10ms |
| Open ports | ss -tlnp |
/proc/net/tcp (filter LISTEN) |
28ms β 10ms |
| USB devices | β | /sys/bus/usb/devices/*/authorized |
~1ms |
| Microphone streams | pactl |
pactl (kept β already 4ms) |
4ms |
Network parsing reads raw hex addresses directly from the kernel's TCP table and maps socket inodes to PIDs via /proc/<pid>/fd β no external tools needed.
| Monitor | Method | CPU when idle |
|---|---|---|
| Camera | inotify IN_OPEN |
~0% (blocked in select) |
| Microphone | pactl poll every 1s | ~0.1% |
| File access | inotify IN_OPEN |
~0% (blocked in select) |
| Package install | /proc poll every 2s | ~0.05% |
| UI refresh | 5s timer | ~0% |
The file access monitor uses Linux inotify, which notifies after a file is opened, not before. This means:
- For most apps (slow reads, document files) SIGSTOP arrives fast enough to prevent meaningful access.
- For fast-reading apps, the first read may complete before the freeze lands.
Why not enforce it like Android?
Android enforces file access at the kernel level because every app runs under a unique UID and the kernel rejects the open() syscall before it completes. On Linux desktop, all your apps share the same UID β the kernel has no app-level boundary to enforce.
The right solution is fanotify FAN_OPEN_PERM β a Linux kernel API that holds the open() syscall suspended until a privileged daemon responds with allow or deny. This would give true pre-emptive blocking identical to Android. It requires CAP_SYS_ADMIN (root privileges) and a dedicated C helper process.
This is not implemented yet because:
- It requires a privileged C daemon β significant complexity
- It has a real performance cost: every
open()in watched directories blocks on a round-trip to the daemon - On a busy system this could noticeably slow down file operations
It may be added in a future version as an opt-in feature for high-security use cases.
| Distro | Package manager | Status |
|---|---|---|
| Debian / Ubuntu / Parrot OS | apt | Fully tested |
| Fedora / RHEL | dnf | Supported |
| Arch Linux / Manjaro | pacman | Supported |
| openSUSE | zypper | Supported |
- Python 3.10+
- PyQt6
pactl(pulseaudio-utils) β microphone monitoringss(iproute2) β network connectionslsusb(usbutils) β USB device listingpkexecβ camera/USB privilege escalation (optional)
All installed automatically by install.sh.
permguard/
βββ __main__.py β `python -m permguard` entry point
βββ main.py β Wires monitors β UI, handles --version/--help
β
βββ core/
β βββ monitor.py β Background QThreads
β β CameraMonitor β inotify on /dev/video*, /proc scan
β β MicMonitor β pactl polling (1s)
β β FileMonitor β inotify on sensitive dirs, /proc scan
β β PackageInstallMonitor β /proc polling for package managers
β β
β βββ permissions.py β JSON rule database (allow/deny/ask)
β βββ data.py β Kernel interface reads (/proc, /sys)
β βββ system.py β kill_pid, camera/mic block, state persist
β βββ firewall.py β iptables per-app network blocking
β βββ usb_control.py β sysfs USB authorized control
β
βββ ui/
βββ permission_dialog.py β Floating Android-style popup
βββ main_window.py β Main window + 12 tabs
βββ widgets.py β StatCard, PermTab, build_table
βββ styles.py β Nord dark theme
-
fanotify FAN_OPEN_PERMβ true pre-emptive file blocking (opt-in, high-security mode) - Clipboard access monitoring
- Per-app network rules (allow specific hosts, block others)
- Flatpak sandbox integration
- Notification history viewer
- App icon recognition in permission dialogs
Bug reports and feature requests: GitHub Issues
- Fork β branch β commit β Pull Request
MIT β free to use, modify, and distribute. See LICENSE.
Ξ± β 1/137
The fine-structure constant β the number that governs how light and matter interact. Some things in the universe just control everything quietly in the background.