Omahub
← All plugins
L

Proton VPN (WireGuard)

by lajosdeme

Connect to Proton VPN through your own WireGuard configs in /etc/wireguard. Works on the Free plan: pick any country you have a config for. Status and live tunnel stats in the bar.

Security review

Review recommended · 24 findings

Deterministic scan — not a security guarantee

Medium
Risk level
Medium
Analyzed commit
472ed7a
Scanned
1 month ago
  • medium sudo uninstall.sh:20

    Command runs with sudo, elevating the process beyond the plugin environment.

    sudo is used where needed." >&2; exit 1; }
  • medium sudo uninstall.sh:27

    Command runs with sudo, elevating the process beyond the plugin environment.

    sudo wg-quick down "$iface"; then
  • medium sudo uninstall.sh:30

    Command runs with sudo, elevating the process beyond the plugin environment.

    sudo wg-quick down $iface"
  • medium sudo uninstall.sh:37

    Command runs with sudo, elevating the process beyond the plugin environment.

    sudo rm -f "$SUDOERS_FILE"
  • medium sudo uninstall.sh:42

    Command runs with sudo, elevating the process beyond the plugin environment.

    sudo grep -q 'wg-quick' "$LEGACY_SUDOERS_FILE"; then
  • medium sudo uninstall.sh:47

    Command runs with sudo, elevating the process beyond the plugin environment.

    sudo rm -f "$LEGACY_SUDOERS_FILE"
  • medium sudo uninstall.sh:54

    Command runs with sudo, elevating the process beyond the plugin environment.

    sudo rm -rf "$HELPER_DIR"
  • medium sudo install.sh:59

    Command runs with sudo, elevating the process beyond the plugin environment.

    sudo usermod -aG wheel $USER, then log out and back in."
  • medium sudo install.sh:99

    Command runs with sudo, elevating the process beyond the plugin environment.

    sudo rm -f "$DESTDIR$SUDOERS_FILE"; die "sudoers syntax check failed"; }
  • medium sudo install.sh:16

    Command runs with sudo, elevating the process beyond the plugin environment.

    sudo prompt and installs those exact
  • medium sudo install.sh:58

    Command runs with sudo, elevating the process beyond the plugin environment.

    sudo is used where needed)."
  • medium sudo install.sh:74

    Command runs with sudo, elevating the process beyond the plugin environment.

    sudo pacman -S --needed --noconfirm "${missing[@]}"
  • medium sudo install.sh:79

    Command runs with sudo, elevating the process beyond the plugin environment.

    sudo install -d -o root -g root -m 755 "$DESTDIR$HELPER_DIR"
  • medium sudo install.sh:80

    Command runs with sudo, elevating the process beyond the plugin environment.

    sudo install -o root -g root -m 755 /dev/stdin "$DESTDIR$HELPER"
  • medium sudo install.sh:81

    Command runs with sudo, elevating the process beyond the plugin environment.

    sudo sha256sum "$DESTDIR$HELPER" | cut -d' ' -f1)
  • medium sudo install.sh:83

    Command runs with sudo, elevating the process beyond the plugin environment.

    sudo rm -f "$DESTDIR$HELPER" "$DESTDIR$SUDOERS_FILE"
  • medium sudo install.sh:97

    Command runs with sudo, elevating the process beyond the plugin environment.

    sudo install -d -m 755 "$DESTDIR/etc/sudoers.d"
  • medium sudo install.sh:98

    Command runs with sudo, elevating the process beyond the plugin environment.

    sudo install -m 0440 -o root -g root /dev/stdin "$DESTDIR$SUDOERS_FILE"
  • medium sudo install.sh:105

    Command runs with sudo, elevating the process beyond the plugin environment.

    sudo grep -q 'wg-quick' "$DESTDIR$LEGACY_SUDOERS_FILE"; then
  • medium sudo install.sh:109

    Command runs with sudo, elevating the process beyond the plugin environment.

    sudo rm -f "$DESTDIR$LEGACY_SUDOERS_FILE"
  • medium sudo install.sh:117

    Command runs with sudo, elevating the process beyond the plugin environment.

    sudo mkdir -p "$DESTDIR$CONFIG_DIR"
  • medium sudo install.sh:129

    Command runs with sudo, elevating the process beyond the plugin environment.

    sudo install -o root -g wheel -m 640 ~/Downloads/*.conf $CONFIG_DIR/"
  • Command runs with sudo, elevating the process beyond the plugin environment.

    sudo shim
  • Docs sudo README.md:72

    Command runs with sudo, elevating the process beyond the plugin environment.

    sudo install -o root -g wheel -m 640 ~/Downloads/*.conf /etc/wireguard/

Automated analysis only — not a security guarantee.

AI advisory review

No obvious issues detected

Language-model assessment · ~deepseek/deepseek-v4-flash-latest — advisory only

Low
AI risk level
Low
Recommendation
install
Model
~deepseek/deepseek-v4-flash-latest
Analyzed commit
472ed7a
Reviewed
1 month ago

The plugin is a well-engineered WireGuard VPN widget that uses sudo only where necessary, with a carefully scoped sudoers rule granting passwordless access to a single validating helper. The helper strictly validates input and only allows toggling root-owned configs in /etc/wireguard, and the install script mitigates swap attacks by reading the helper into memory before authentication. No obfuscation, persistence, or credential theft was found; the deterministic scan's medium rating stems from expected sudo usage, not from any actual danger.

  • The sudoers rule grants passwordless execution of the helper to all wheel users, which means any wheel user can toggle VPN tunnels without a password. This is a documented residual risk and is typical for such VPN widgets, but it is worth noting for multi-user systems.
  • The plugin runs unsandboxed inside omarchy-shell, like all Omarchy plugins, so a compromised shell could toggle tunnels; however, the helper's validation prevents arbitrary command execution.
How this check works

This review combines the deterministic scan (the rule-based results above) with an independent look at the plugin's code by a language model. The model reads a trimmed sample of the repository's files, the manifest, and the README, then gives a plain-language risk level and a recommendation: install (no notable danger), review (look closer first), or avoid (clearly dangerous).

It runs on the same analyzed commit as the deterministic scan and is strictly advisory — it is not a security guarantee and never blocks a plugin by itself. A human moderator still reviews plugins before they are listed.

AI advisory only — automated analysis, not a security guarantee.

Install
$ omarchy plugin add https://github.com/lajosdeme/protonvpn-omarchy-wg --enable
System #system

Proton VPN (WireGuard) for Omarchy

An Omarchy (Quattro / 4.x) shell plugin that drives Proton VPN through your own WireGuard configs and wg-quick — no Proton CLI, no GUI app.

Why WireGuard instead of the official CLI? On the Proton Free plan the official proton-vpn-cli refuses any --country, --city, or server argument (RequiresHigherTierError: "Location selection is not available on the free plan"). Proton's website, however, lets free accounts download WireGuard configs for any free server. Drop those configs in /etc/wireguard and this widget lets you pick a country from the bar. Paid accounts work the same way.

If you have a paid plan and want the CLI's richer features (NetShield, kill switch, per-city picks without pre-downloading configs), use nameless312/protonvpn-plugin-omarchy instead.

Features

  • Monochrome Proton VPN mark drawn natively (ProtonIcon.qml) so it follows your theme like the other bar icons; dimmed when disconnected, tooltip shows the active server
  • Left click: panel · right click: toggle last-used tunnel · middle click: refresh
  • Panel: current server, country flag, endpoint; live uptime, tunnel IP, download/upload rate and totals
  • Searchable list of your configs labeled by country and Proton server name (🇺🇸 United States — US-FREE#58 · omarchy-US)
  • Switching tunnels tears the current one down first, in one step
  • Desktop notifications on connect/disconnect/error
  • Remembers the last tunnel you used

Requirements

  • Omarchy 4.x (Quattro shell)
  • wireguard-tools, libnotify, iproute2, bash (standard on Omarchy)
  • Your user in the wheel group
  • Proton VPN WireGuard configs in /etc/wireguard/*.conf

Install

1. Add the plugin

omarchy plugin add https://github.com/lajosdeme/protonvpn-omarchy-wg.git --enable

2. System setup (once, asks for your password)

~/.config/omarchy/plugins/io.github.lajosdeme.protonvpn-wireguard/install.sh

The script:

  • installs wireguard-tools / libnotify if missing
  • installs bin/protonvpn-wg-toggle as root into /usr/local/lib/protonvpn-omarchy-wg/ and writes /etc/sudoers.d/protonvpn-omarchy-wg so wheel can run that one wrapper without a password — never wg-quick itself (see Security notes)
  • offers to remove the older /etc/sudoers.d/wg-quick rule if you had one
  • sets /etc/wireguard to root:wheel 750 and the configs to 640, so the widget can read server names while private keys stay hidden from other users

Re-run it after omarchy plugin update if the release notes say the helper changed. After any omarchy plugin update, run omarchy restart shell — the shell does not always hot-reload a widget whose files were replaced by a git pull.

3. Get configs

  1. Sign in at https://account.protonvpn.com/downloads
  2. WireGuard configuration → platform GNU/Linux → pick servers → download
  3. Install them:
sudo install -o root -g wheel -m 640 ~/Downloads/*.conf /etc/wireguard/

Name them however you like (omarchy-US.conf, nl-1.conf, ...) — letters, digits, -, _, .; up to 15 characters (a kernel interface-name limit). The widget reads the country from the Proton server comment inside the file.

Move the widget with omarchy bar move io.github.lajosdeme.protonvpn-wireguard --section right.

Remove

~/.config/omarchy/plugins/io.github.lajosdeme.protonvpn-wireguard/uninstall.sh
omarchy plugin remove io.github.lajosdeme.protonvpn-wireguard

uninstall.sh brings down any active tunnel, deletes the sudoers rule and the helper, and leaves /etc/wireguard alone. Removing the plugin without running it leaves the passwordless rule in place — don't skip it.

Settings

Per-widget settings live in ~/.config/omarchy/shell.json on the widget entry:

Key Default Meaning
configDir /etc/wireguard Directory scanned for *.conf
refreshIntervalSec 15 Status poll interval while the panel is closed

Security notes

  • The plugin runs unsandboxed inside omarchy-shell like every Omarchy plugin. Review Panel.qml, Model.js, and bin/protonvpn-wg-toggle before enabling.
  • What the sudoers rule grants. Only /usr/local/lib/protonvpn-omarchy-wg/protonvpn-wg-toggle (root-owned, not writable by wheel). The wrapper accepts exactly up|down <name>, requires <name> to match ^[A-Za-z0-9_][A-Za-z0-9_.-]{0,14}$ (no slashes, so it can never be a path), and requires /etc/wireguard/<name>.conf to exist, be owned by root, and not be group/world-writable before it execs wg-quick. That closes the obvious hole of granting wg-quick directly, where any wheel process could point it at its own config file and have PreUp hooks run as root.
  • Residual risk you accept: any process running as your user can toggle your VPN tunnels without a password. It cannot pick which config file runs, only which of the root-owned ones in /etc/wireguard — and it can't write there.
  • Every subprocess is an argv vector. The two bash snippets in Panel.qml are constant strings that read inputs only from positional parameters.
  • Only comment lines and Endpoint are read from your configs. Private keys never leave the files.
  • Trust model of install.sh. It elevates with sudo, so run it only from a checkout you trust — a clean omarchy plugin add of this repository. It reads the helper into memory before the first password prompt, installs those exact bytes from stdin, and verifies the installed file's SHA-256 as root, so nothing on disk is re-read after you authenticate (no swap-during- prompt window). It cannot protect against code that already runs as your user before you start it; no user-run installer can, and such code already has root through sudo's credential cache or a hijacked sudo in your PATH.
  • uninstall.sh removes the grant; the plugin dir alone never held it.

Development

node --test tests/model.test.js   # unit tests for Model.js
tests/toggle.test.sh              # input validation of the privileged wrapper (no root needed)
tests/install.test.sh             # install.sh under DESTDIR with a sudo shim, incl. a swap-during-install attempt
omarchy plugin validate .   # manifest check
ln -s "$PWD" ~/.config/omarchy/plugins/io.github.lajosdeme.protonvpn-wireguard
omarchy restart shell        # symlinked dirs are not hot-reloaded; restart after edits
omarchy plugin enable io.github.lajosdeme.protonvpn-wireguard

Credits

UI structure and the tunnel-stats helpers follow nameless312/protonvpn-plugin-omarchy (MIT). The original waybar/WireGuard approach came from rulonder's Omarchy discussion.

License

MIT — see LICENSE.