Proof Portal

Project overview

Omarchy

ProbeLabs65 findings · 95 requirements

A proof layer — requirements, tests and verified fixes — for two of Omarchy's subsystems: the application menu (launcher scripts, QML model, JSONC config, search and selection) and the lock screen (lock scripts, QML, PAM authentication). Scope is deliberately limited to those components of omacom/omarchy; the rest of the distribution is not covered.

Inbox
ReportR-4638GitHub issuePublicReceived

Network panel reports ethernet and hides Wi-Fi list when a VPN tunnel (wg/tun/tap) is the default route

Reported by kernelkiranerys · filed Aug 20, 2026Closed upstream on 2026-09-21 by bjarneo via an automated message, as a duplicate of #7438 (R-1669). GitHub close reason: completed.

Received and recorded verbatim. Nothing has been checked yet.

At a glance

1 · What is claimed?
Only the report text below — no validator has restated it as checkable claims yet.
2 · What does it affect?
Not yet mapped to any requirement or component.
3 · Is it reproducible?
No validation has been run yet.
4 · What remains unclear?
  • Not validated yet: no claims, no reproducer.
5 · What happens next?
Our staff decide whether the report is valid. Where this project allows it, agents decide whether it duplicates another report or a known issue. No decision has been recorded yet.

Original report

Network panel reports ethernet and hides Wi-Fi list when a VPN tunnel (wg/tun/tap) is the default routerevision 1 · captured 2026-10-04 12:03 UTC via poll

Network panel reports "ethernet" and hides Wi-Fi list when a VPN (WireGuard/OpenVPN) tunnel is the default route

Summary

When a VPN tunnel interface (e.g. Mullvad WireGuard wg0-mullvad, or any wg*/tun*/tap* device) holds the default route, the Omarchy network panel misidentifies the connection as ethernet and the Wi-Fi network list fails to populate, even though the host is connected over Wi-Fi and has a working internet connection. The root cause is that omarchy-network-status (the helper backing the panel) selects the "active" interface by reading the default route, with no filter for tunnel/virtual interfaces.

Environment

  • Omarchy: 4.0.0-1 (quattro)
  • Kernel: 7.1.8-arch1-3
  • OS: Omarchy (Arch), VERSION_ID=4.0.0
  • NetworkManager backend: yes (nmcli available)
  • VPN in use: Mullvad, WireGuard interface wg0-mullvad, managed by mullvad-daemon
  • Debug log: /tmp/omarchy-debug.log (generated via omarchy debug --no-sudo --print)

Reproduction

  1. Connect to Wi-Fi (here: Zen Internet - FRITZ!Box KT on wlan0, 5 GHz).
  2. Bring up a VPN that installs a default route via a WireGuard/tun interface:
   mullvad connect
  1. Open the Omarchy network panel.

Expected

Panel shows the Wi-Fi connection (SSID, signal, band), with the Wi-Fi network list populated.

Actual

Panel reports "ethernet" with the tunnel interface name and shows no Wi-Fi networks, even though wlan0 is connected and the internet works. At a different location where the same VPN was up, the panel listed no Wi-Fi devices at all.

Root cause

/usr/bin/omarchy-network-status resolves the active interface like this:

device=$(ip route get "$internet_probe" 2>/dev/null | awk '{ for (i = 1; i <= NF; i++) if ($i == "dev") { print $(i + 1); exit } }')

if [[ -z $device ]]; then
  printf 'disconnected\t\t\t\n'
  return
fi

if [[ ! -d /sys/class/net/$device/wireless ]]; then
  printf 'ethernet\t%s\t\t\n' "$device"
  return
fi

With a VPN up, ip route get 1.1.1.1 returns the tunnel (wg0-mullvad). Tunnels have no /sys/class/net/<iface>/wireless directory, so the script unconditionally prints ethernet and exits before ever reaching the Wi-Fi branch. The --verbose path mirrors the same flaw: it derives iface from the default-route dev and emits type ethernet for any non-wireless interface, including tunnels.

Evidence

Mullvad connected, before the workaround (stock binary):

$ omarchy-network-status
ethernet	wg0-mullvad

$ omarchy-network-status --verbose
iface	wg0-mullvad
ip	10.142.91.41
prefix	32
gateway
rx_bytes	31147048
tx_bytes	4090120
type	ethernet
speed
duplex
internet_ping_ms	131

/sys/class/net/wg0-mullvad/wireless does not exist, and cat /sys/class/net/wg0-mullvad/speed fails with Invalid argument (tunnels don't expose ethtool-style link attributes). The physical link is in fact Wi-Fi:

$ nmcli -t -f DEVICE,TYPE,STATE,CONNECTION device status
wlan0:wifi:connected:Zen Internet - FRITZ!Box KT
wg0-mullvad:wireguard:connected (externally):wg0-mullvad
enp0s31f6:ethernet:unavailable:

The same binary with the VPN down reports the connection correctly:

$ mullvad disconnect
$ omarchy-network-status
wifi	Zen Internet - FRITZ!Box KT	78	5220.0

Impact

  • The bar pill shows an ethernet icon and the wrong interface/SSID while a VPN is up.
  • The panel's Wi-Fi network list does not populate, so users cannot scan, switch networks, or generate a Wi-Fi QR code while the VPN is running — a common, always-on scenario for VPN users.
  • The "router" ping row is empty because tunnel routes are point-to-point and carry no gateway.
  • speed/duplex reads on tunnel interfaces emit cat: ... Invalid argument noise into the verbose output.

Suggested fix

Filter tunnel/virtual interfaces when resolving the active interface, so the panel always reflects the underlying physical link. A minimal change to print_status and print_verbose:

is_tunnel() { case "$1" in wg*|tun*|tap*) return 0;; *) return 1;; esac; }

# Resolve the physical interface: default route first, falling back to the
# first UP non-tunnel interface with an IPv4 address.
physical_iface() {
  local dev
  dev=$(ip route get "$internet_probe" 2>/dev/null | awk '{ for (i=1;i<=NF;i++) if ($i=="dev") { print $(i+1); exit } }')
  if [[ -n $dev ]] && ! is_tunnel "$dev"; then echo "$dev"; return; fi
  ip -o -4 addr show 2>/dev/null | awk -F': ' '{
    iface=$2; sub(/ .*/, "", iface)
    if (iface == "lo") next
    if (iface ~ /^(wg|tun|tap)/) next
    print iface; exit
  }'
}

Use physical_iface in place of the raw ip route get ... dev lookup in both print_status and print_verbose. In print_verbose, also derive the gateway from the physical interface's default route (ip route show default) rather than the (tunnel) route-get record, and guard speed/duplex reads so tunnel devices don't emit cat: Invalid argument.

This is a user-facing display-only change; it does not affect routing or the VPN itself.

Workaround applied locally

A shim replacing /usr/bin/omarchy-network-status (original backed up to /usr/bin/omarchy-network-status.real) implements the fix above. With Mullvad connected it now reports the physical Wi-Fi link:

$ omarchy-network-status
wifi	Zen Internet - FRITZ!Box KT	78	5220.0

$ omarchy-network-status --verbose
iface	wlan0
ip	192.168.178.112
prefix	24
gateway	192.168.178.1
rx_bytes	142746692
tx_bytes	13443648
type	wifi
ssid	Zen Internet - FRITZ!Box KT
signal_dbm	-43
freq	5220.0
bitrate	866.7 MBit/s
router_ping_ms	1.69
internet_ping_ms	132

After omarchy restart shell, the bar pill and panel display Wi-Fi correctly with the VPN up. Note the shim lives in the packaged binary path and will be overwritten by omarchy update; a proper upstream fix would remove the need to re-apply it.

Notes

  • The bar pill itself (Panel.qml lines 435-443) derives kind from Quickshell.Networking's native NetworkManager state (connectedWifiNetwork), not from this script, so the pill can show the right icon even when the script is wrong — but the panel body relies on the script's --verbose output for info.type, iface, ssid, etc. That's why the pill occasionally read "disconnected" until a shell restart re-synced the native service after toggling the VPN.
  • The same misclassification would affect any VPN that installs a default route via a non-wireless virtual interface (OpenVPN tun0, WireGuard wg0, etc.), not just Mullvad.
View raw text
# Network panel reports "ethernet" and hides Wi-Fi list when a VPN (WireGuard/OpenVPN) tunnel is the default route

## Summary

When a VPN tunnel interface (e.g. Mullvad WireGuard `wg0-mullvad`, or any `wg*`/`tun*`/`tap*` device) holds the default route, the Omarchy network panel misidentifies the connection as **ethernet** and the Wi-Fi network list fails to populate, even though the host is connected over Wi-Fi and has a working internet connection. The root cause is that `omarchy-network-status` (the helper backing the panel) selects the "active" interface by reading the default route, with no filter for tunnel/virtual interfaces.

## Environment

- Omarchy: 4.0.0-1 (quattro)
- Kernel: 7.1.8-arch1-3
- OS: Omarchy (Arch), `VERSION_ID=4.0.0`
- NetworkManager backend: yes (`nmcli` available)
- VPN in use: Mullvad, WireGuard interface `wg0-mullvad`, managed by `mullvad-daemon`
- Debug log: `/tmp/omarchy-debug.log` (generated via `omarchy debug --no-sudo --print`)

## Reproduction

1. Connect to Wi-Fi (here: `Zen Internet - FRITZ!Box KT` on `wlan0`, 5 GHz).
2. Bring up a VPN that installs a default route via a WireGuard/tun interface:
   ```
   mullvad connect
   ```
3. Open the Omarchy network panel.

### Expected

Panel shows the Wi-Fi connection (SSID, signal, band), with the Wi-Fi network list populated.

### Actual

Panel reports "ethernet" with the tunnel interface name and shows **no Wi-Fi networks**, even though `wlan0` is connected and the internet works. At a different location where the same VPN was up, the panel listed no Wi-Fi devices at all.

## Root cause

`/usr/bin/omarchy-network-status` resolves the active interface like this:

```bash
device=$(ip route get "$internet_probe" 2>/dev/null | awk '{ for (i = 1; i <= NF; i++) if ($i == "dev") { print $(i + 1); exit } }')

if [[ -z $device ]]; then
  printf 'disconnected\t\t\t\n'
  return
fi

if [[ ! -d /sys/class/net/$device/wireless ]]; then
  printf 'ethernet\t%s\t\t\n' "$device"
  return
fi
```

With a VPN up, `ip route get 1.1.1.1` returns the tunnel (`wg0-mullvad`). Tunnels have no `/sys/class/net/<iface>/wireless` directory, so the script unconditionally prints `ethernet` and exits before ever reaching the Wi-Fi branch. The `--verbose` path mirrors the same flaw: it derives `iface` from the default-route `dev` and emits `type ethernet` for any non-wireless interface, including tunnels.

### Evidence

Mullvad connected, **before** the workaround (stock binary):

```
$ omarchy-network-status
ethernet	wg0-mullvad

$ omarchy-network-status --verbose
iface	wg0-mullvad
ip	10.142.91.41
prefix	32
gateway
rx_bytes	31147048
tx_bytes	4090120
type	ethernet
speed
duplex
internet_ping_ms	131
```

`/sys/class/net/wg0-mullvad/wireless` does not exist, and `cat /sys/class/net/wg0-mullvad/speed` fails with `Invalid argument` (tunnels don't expose ethtool-style link attributes). The physical link is in fact Wi-Fi:

```
$ nmcli -t -f DEVICE,TYPE,STATE,CONNECTION device status
wlan0:wifi:connected:Zen Internet - FRITZ!Box KT
wg0-mullvad:wireguard:connected (externally):wg0-mullvad
enp0s31f6:ethernet:unavailable:
```

The same binary with the VPN down reports the connection correctly:

```
$ mullvad disconnect
$ omarchy-network-status
wifi	Zen Internet - FRITZ!Box KT	78	5220.0
```

## Impact

- The bar pill shows an ethernet icon and the wrong interface/SSID while a VPN is up.
- The panel's Wi-Fi network list does not populate, so users cannot scan, switch networks, or generate a Wi-Fi QR code while the VPN is running — a common, always-on scenario for VPN users.
- The "router" ping row is empty because tunnel routes are point-to-point and carry no gateway.
- `speed`/`duplex` reads on tunnel interfaces emit `cat: ... Invalid argument` noise into the verbose output.

## Suggested fix

Filter tunnel/virtual interfaces when resolving the active interface, so the panel always reflects the underlying physical link. A minimal change to `print_status` and `print_verbose`:

```bash
is_tunnel() { case "$1" in wg*|tun*|tap*) return 0;; *) return 1;; esac; }

# Resolve the physical interface: default route first, falling back to the
# first UP non-tunnel interface with an IPv4 address.
physical_iface() {
  local dev
  dev=$(ip route get "$internet_probe" 2>/dev/null | awk '{ for (i=1;i<=NF;i++) if ($i=="dev") { print $(i+1); exit } }')
  if [[ -n $dev ]] && ! is_tunnel "$dev"; then echo "$dev"; return; fi
  ip -o -4 addr show 2>/dev/null | awk -F': ' '{
    iface=$2; sub(/ .*/, "", iface)
    if (iface == "lo") next
    if (iface ~ /^(wg|tun|tap)/) next
    print iface; exit
  }'
}
```

Use `physical_iface` in place of the raw `ip route get ... dev` lookup in both `print_status` and `print_verbose`. In `print_verbose`, also derive the gateway from the physical interface's default route (`ip route show default`) rather than the (tunnel) route-get record, and guard `speed`/`duplex` reads so tunnel devices don't emit `cat: Invalid argument`.

This is a user-facing display-only change; it does not affect routing or the VPN itself.

## Workaround applied locally

A shim replacing `/usr/bin/omarchy-network-status` (original backed up to `/usr/bin/omarchy-network-status.real`) implements the fix above. With Mullvad connected it now reports the physical Wi-Fi link:

```
$ omarchy-network-status
wifi	Zen Internet - FRITZ!Box KT	78	5220.0

$ omarchy-network-status --verbose
iface	wlan0
ip	192.168.178.112
prefix	24
gateway	192.168.178.1
rx_bytes	142746692
tx_bytes	13443648
type	wifi
ssid	Zen Internet - FRITZ!Box KT
signal_dbm	-43
freq	5220.0
bitrate	866.7 MBit/s
router_ping_ms	1.69
internet_ping_ms	132
```

After `omarchy restart shell`, the bar pill and panel display Wi-Fi correctly with the VPN up. Note the shim lives in the packaged binary path and will be overwritten by `omarchy update`; a proper upstream fix would remove the need to re-apply it.

## Notes

- The bar pill itself (`Panel.qml` lines 435-443) derives `kind` from Quickshell.Networking's native NetworkManager state (`connectedWifiNetwork`), not from this script, so the pill can show the right icon even when the script is wrong — but the panel body relies on the script's `--verbose` output for `info.type`, `iface`, `ssid`, etc. That's why the pill occasionally read "disconnected" until a shell restart re-synced the native service after toggling the VPN.
- The same misclassification would affect any VPN that installs a default route via a non-wireless virtual interface (OpenVPN `tun0`, WireGuard `wg0`, etc.), not just Mullvad.

Validation

Not checked yet. A validator will restate this report as checkable claims, map it to the project's requirements and write a reproducer that the proof engine runs.

Linked

Not linked to any known issue, other report or change yet.

Decision

Decisions are recorded by our staff — or, where this project allows it, by agents: checked by a second, independent agent, or by a single agent where the project's policy says so. Any decision reached so far is shown below.

No decision has been recorded yet.