[Bug]: macOS — /tmp/verge is created as root:_mbsetupuser (an empty group), so the GUI can't reach its own IPC socket; proxy page blank while proxying works
Verify steps / 验证步骤
- I have searched existing issues (#4579, #6444, #7015, #6978 are related but have a different root cause)
Describe the bug / 问题描述
On macOS 26.5, the proxy page is completely blank while proxying itself works fine.
The root cause is not a config error or a socket path mismatch (as in #7015). Both binaries agree on the path. The problem is the ownership of /tmp/verge:
drwxrws--- 7 root _mbsetupuser 224 Sep 11 11:04 /tmp/verge
The privileged service creates the directory as root:_mbsetupuser with mode 770 — no permission for "other". But on macOS 26.5, _mbsetupuser has no members at all:
$ dscl . -read /Groups/_mbsetupuser GroupMembership
No such key: GroupMembership
The GUI runs as the normal user (mac), which is neither the owner nor a member of that group, so it cannot access its own IPC socket:
$ ls /tmp/verge/
ls: /tmp/verge/: Permission denied
Log shows:
[Validate] 验证成功 ← config is valid
[Core] Failed to apply configuration by mihomo api, restart core to apply it,
error msg: Connection failed, I/O error: Permission denied (os error 13)
So the config is fine, the kernel is fine — the GUI just can't talk to it.
Additional context / 补充信息
1. Two mihomo cores run simultaneously and fight over the same socket
PID USER
33988 root ← spawned by the privileged service
34458 mac ← spawned by the GUI in sidecar mode
Whichever one wins the socket determines what the GUI sees. When the root one wins, the GUI reads its config (7 nodes, only GLOBAL) instead of the real one (35 nodes, 4 groups). sudo pkill doesn't help — the service immediately respawns it.
2. Reinstalling does not help
Reinstalling the service via the bundled clash-verge-service-install, and even a full uninstall + clean reinstall (removing the app, the service bundle, the LaunchDaemon, /tmp/verge, and all user data), reproduces the exact same ownership every time. The behaviour appears to be hardcoded.
3. /tmp/verge is hardcoded in both binaries
$ strings .../MacOS/clash-verge | grep -oE "2\.[0-9]\.[0-9]/tmp/verge/.*\.sock"
2.3.3/tmp/verge/clash-verge-service.sock
$ strings .../MacOS/clash-verge-service | grep -oE "2\.[0-9]\.[0-9]/tmp/verge/.*\.sock"
2.3.3/tmp/verge/clash-verge-service.sock
Note the embedded version is 2.3.3 while the app reports 2.5.2. Unlike #7015 the paths do match here, but there is no way for a user to relocate the socket away from /tmp — it is not exposed as a setting.
4. Switching to the TCP external controller does not work either
Enabling the external controller writes external-controller: 127.0.0.1:9090 and a secret into clash-verge.yaml, and the port does listen. But every request is rejected:
$ curl -s http://127.0.0.1:9090/version
{"message":"Unauthorized"}
Passing the secret manually works and returns the full, correct data:
$ curl -s http://127.0.0.1:9090/proxies -H "Authorization: Bearer <secret>"
groups: GLOBAL, OneCat, 故障转移, 自动选择 nodes: 35
The secret is written to clash-verge.yaml (the core's config) but never stored in verge.yaml (the GUI's own config, 64 keys, no secret field). So the GUI does not know its own secret and 401s itself. Changing the secret in the UI does not fix this.
Workaround
Grant the user an ACL on the directory. This survives the service resetting the owner (ACLs are independent of owner/group) and takes effect immediately without re-login:
sudo chmod +a "$(whoami) allow list,search,add_file,add_subdirectory,delete_child,\
readattr,writeattr,readextattr,writeextattr,readsecurity,file_inherit,directory_inherit" /tmp/verge
sudo pkill -9 -f verge-mihomo
After this the GUI reads the socket correctly and all proxy groups appear. Resets on reboot, since /tmp is cleared at boot.
Adding the user to _mbsetupuser also works but requires logging out and back in.
Suggested fixes
- Don't place the IPC socket in
/tmp— use~/Library/Application Support/<bundle-id>/or/var/run/, and make it configurable. - Don't rely on
_mbsetupuser; on current macOS it is an empty group. Chown the directory to the console user, or use mode777on the directory with0600on the socket. - Make sure only one mihomo core runs — the service-spawned one and the sidecar one currently race for the same socket.
- Persist the external-controller secret in
verge.yamlso the GUI can authenticate against its own TCP endpoint.
OS / 操作系统
- MacOS
OS Version / 操作系统版本
macOS 26.5 (25F71), Apple Silicon (arm64)
Clash Verge Rev Version / 版本
2.5.2 (GUI) / 2.3.3 (embedded service binary)
Source: clash-verge-rev/clash-verge-rev