CodeVetter · Repo Unpack · Risk map
clash-verge-rev/clash-verge-rev
The highest-impact code is the core lifecycle and the system-proxy/TUN apply path: a bad transition can leave the OS proxy half-set or the core unguarded. The webview is loosely sandboxed (CSP off, filesystem scope **). Profile JavaScript is sandboxed in Boa but can still rewrite the config that Mihomo will load. Secrets at rest are only as private as the app-data directory, because the AES key sits beside verge.yaml. Deep links import remote subscriptions immediately, and a user-configured startup script is executed as a shell.
- tauri.conf.json sets CSP to null and enables the asset protocol with allow ** and requireLiteralLeadingDot false. Capability migrated grants fs:allow-read-file and fs:allow-write-file with scope $APPDATA/**, $RESOURCE/../**, and **. desktop-capability allows http and https to any host via http:allow-fetch.
- PAC is mounted with .or(pac) outside instance_auth. Any local process that can reach 127.0.0.1 on the embedded port can read the PAC body, including the mixed port, once PAC_AVAILABLE is true. Window-restore and scheme import stay behind x-instance-token.
- startup_script executes an arbitrary existing .sh via bash or .ps1/.bat via powershell from a path stored in verge config, during every startup, with the script directory as cwd.
- resolve_scheme imports a subscription as soon as the URL parses. There is no confirm command on that path. A clash:// or clash-verge:// link that reaches the primary instance therefore downloads and saves a remote profile.
- WebDAV secrets are encrypted in verge.yaml, but get_encryption_key stores the raw 32-byte key in app_home/.encryption_key with no OS keychain. A local reader of that directory can decrypt the fields. (inferred)
- check_media_unlock's HTTP client sets danger_accept_invalid_certs(true) and danger_accept_invalid_hostnames(true) and forces traffic through http://127.0.0.1:<mixed port>. Unlock checks can succeed against intercepted TLS.
- System proxy writes are classified as SysproxyFailure: SYSPROXY_PRIVILEGE_REQUIRED, SYSPROXY_DIRECT_FALLBACK, SYSPROXY_SIDECAR_WHILE_SERVICE_READY, SYSPROXY_GUARD_STOPPED, SYSPROXY_CORE_NOT_READY, and SYSPROXY_SYSTEM_CALL_FAILED. SystemProxyStateUnknown means a write was left partly applied and a turn-off was attempted. rollback_failure keeps the actionable code.
- Windows service start uses run_service_start_with_sidecar_fallback. A non-location ServiceStartRefusal is returned rather than ignored. An unclear occupancy probe blocks sidecar fallback. Sidecar continuation is rejected unless can_allow_sidecar_for_session matches mode and status, and a failed sidecar attempt withdraws the allowance and rolls back the proxy.
- Updater endpoints prefer https://update.hwdns.net/... and https://gh-proxy.org/... ahead of the GitHub release update.json. Payloads are still checked with the configured minisign pubkey, but availability depends on those proxies.
- Config validation and the running core shell out to a sidecar binary named by verge's clash core (verge-mihomo or verge-mihomo-alpha). Replacing that binary in the install or sidecar directory changes what -t and the runtime execute.
- Profile scripts are not a browser sandbox escape, but they do receive the full clash mapping and their returned object becomes the runtime config after authoritative-field enforcement. A malicious local script profile can still rewrite rules and proxies within those limits. Remote subscriptions are YAML fetched by PrfItem::from_url, not executed as JavaScript by themselves.
- Lock order is documented as config write lock then lifecycle lock. continue_with_sidecar and uninstall_service_and_start_sidecar both comment that taking them in the other order can commit another transaction's staged verge patch.
- Linux desktop file template declares only MimeType x-scheme-handler/clash, while init_scheme registers both clash and clash-verge via xdg-mime. A packaging drift can leave clash-verge:// unregistered even though Tauri lists both schemes.