* fix(security): 修复辅助工具鉴权降级与五处正确性缺陷
代码审查(安全/质量/性能/架构四维度)发现的问题,逐条修复。
辅助工具鉴权(High)
ad-hoc 构建下 clientRequirement 退化为只校验 bundle identifier,不含
anchor 约束,任何进程 codesign -s - 伪造同名即可连上 root 辅助工具,
驱动 DNS、睡眠、本地快照与风扇。project.yml 默认就是 ad-hoc 签名,
而 make build 是文档化的安装路径,开发机上属常态。
改为无团队签名时返回 nil 并拒绝连接,与在线升级在 ad-hoc 下直接禁用
的策略一致;此时 App 走一次性管理员授权回退,功能不丢。
卸载器批量误删
validate 只拒绝 com.apple. 前缀,包名为 "com" 的应用可通过;随后
hasPrefix("com.") 把 leftovers 扫描的十余个目录(Preferences、Caches、
Containers、Saved Application State 等)下所有 com.* 条目当成残留列出
并默认勾选,一次点击即整体移入废纸篓。前缀匹配改为要求至少三段反向
域名,精确匹配不受影响。
退出时静默跳过恢复睡眠
restoreDefaultsSynchronously 的 guard 在循环体内用 return 而非 continue,
第一步取代理失败就连带跳过第二步,Mac 保持禁止睡眠。同时把两步各等 1 秒
改为总预算 1.5 秒,避免主线程退出卡顿。
公网 IP 查询重入保护失效
isLookingUpPublic 同时承担重入锁与转圈开关两个相反职责,有缓存且非强制
刷新时恒为 false,guard 形同虚设,两个 Task 可各发三次请求并发写缓存,
失败结果可能覆盖好结果。拆出独立的 isFetchingPublic,并用 defer 确保
所有退出路径复位。
诊断导出的崩溃报告未脱敏
日志与清理记录都走了 redact,但 .ips 崩溃报告原样入包,其中可能夹带
进程内存中的 WebDAV 目录、用户名、公网 IP 与主机名,与界面“不含 IP、
序列号与硬件地址”的声明不符。改为同样脱敏后写入。
PowerSampler
channels(in:) 的 unsafeBitCast 改为 Unmanaged.fromOpaque.takeUnretainedValue。
未加 deinit 释放 IOReport 订阅:IOReport 是私有框架,无公开释放入口且
无法验证其是否为 CF 对象,而全进程只有一个 PowerSampler、订阅各只创建
一次且随进程存在,不是增长型泄漏——已就此写明注释。
补回归测试:clientRequirement 的 ad-hoc 分支与 anchor 约束、
matchesIdentifier 的过宽前缀与派生名匹配。
make test 141 项通过(新增 4 项),Release 完整构建通过。
* fix(security): 完善辅助工具升级与卸载边界校验
* fix(ui): 拆分评分条视图以解决 CI 类型检查超时
* fix(webdav): 规范化目录路径以兼容 macOS 15
XStats
Your Mac at a glance — CPU, GPU, memory, network and temperatures in the menu bar, with fan control, keep-awake, one-click cleanup, an app uninstaller and an IP cleanliness check.
XStats is a macOS menu-bar app that shows what your Mac is doing right now — per-core CPU load, GPU, memory pressure, network speed, disk, battery, temperatures and fans — and lets you act on it: spin the fans up, keep the Mac awake with the lid closed, clear caches, fully uninstall apps and disable startup items. Network details also check how clean your public IP is — whether it is flagged as a VPN, proxy, data center or for abuse. Everything is read on your own Mac, and there is no telemetry. No XStats account is required: manually back up and restore preferences through your own WebDAV server. Other optional network features include a public-IP and cleanliness lookup when you open network details, a ping probe to a target you choose, and a daily check for a new version.
Install
Check GitHub Releases for published XStats builds. Choose AppleSilicon or Intel for your Mac. If no build is available, follow the source-build instructions below.
XStats has no website yet. Automatic updates and the existing GeoIP service are unchanged; account login has been replaced with manual WebDAV sync. The update installer still verifies bundle identity and signatures: packages built for OpenStats cannot replace XStats.
Requires macOS 14 (Sonoma) or later. Developed and tested mainly on Apple silicon; on Intel Macs, Apple Intelligence process explanations are unavailable, CPU cores are not split into performance and efficiency groups, and some power and frequency readings may be missing. The interface supports Simplified Chinese, Traditional Chinese, Japanese, Korean, English, German, Spanish, French and Arabic. It detects your preferred system language by default. Search and switch languages in Settings → General → Language; Arabic uses a right-to-left layout.
Recent updates
Latest release 0.6.1 (2026-09-18) · 3 changes in development · full changelog (kept in Chinese)
Activity
At a glance
Where the numbers show
Menu bar
- Eight styles, chosen once for every metric: two-line text, one-line text, icons, rings, pies, history bars, level meters and status dots. Any metric can be given its own style; Settings previews each one with sample data and says what the shape means.
- Network speed in two rows with dots or arrows, or on one line — green for upload, blue for
download, always with its unit (
KB/s,MB/s,GB/s). - Small and consistent type: 7 pt labels over 10 pt figures, 11 pt on one line, 9 pt for network speed. Figures are fixed-width, so the bar does not jitter. Hover for every reading.
Detail popovers — each metric gets its own menu-bar item; click it for a narrow popover.
Choose which sections each popover shows in Settings. Esc closes it.
- CPU. Usage with a status and 30-second change, thermal headroom; a per-core heatmap; load by core type; queueing (load average per core, rising or falling); usage summed by app.
- Memory. What is still available with a pressure timeline; a waterline bar; memory saved by compression and live swap I/O; usage summed by app.
- Network. Traffic history; a connection-probe grid (green when reachable, red when not, last 60 pings); interface, Wi-Fi signal, VPN / proxy; local and public IPv4 / IPv6 with a flag, region and ASN; an IP cleanliness score with an F to A+ grade and risk flags (VPN, proxy, Tor, data center, abuse); DNS flush and one-click switching to Cloudflare, Google, Tencent, Alibaba Cloud or manual servers; per-process traffic.
- Disk. Startup disk capacity as a segmented bar (used, purgeable, available); read / write speed with a 60-second history; SSD health; the apps reading and writing the most.
- GPU, Temperature & fans. History, sensor groups, fan speeds and quick modes.
- Battery. Charge level, time remaining, adapter wattage and battery temperature; a 24-hour charge curve; power draw; health and cycle count; the batteries of connected Bluetooth devices (AirPods, Magic Keyboard / Mouse / Trackpad). Macs without a battery show the Bluetooth devices only.
IP cleanliness check — see at a glance whether your public IP is clean: the CleanIP.io score with an F to A+ grade band, a risk score and the risk flags it hits (VPN, proxy, Tor, data center, abuse history and more); the IP address block marks native vs. broadcast and residential vs. data center with badges. IPv4 and IPv6 are checked separately, and results are cached on the Mac for 7 days unless the address changes or you refresh.
Main window — a sidebar with Dashboard, This Mac, History, CPU, GPU, Memory, Disk, Network, Temperature & fans, Battery, plus the Processes, Startup items, Keep awake, Clean and Uninstall tools; resizable in both directions. See Cleanup.
Ask Apple Intelligence about a process — right-click a process you don't recognise and the on-device model explains what it is, whether its usage looks normal and whether it is safe to quit. No third-party AI and no network; requires macOS 26 with Apple Intelligence turned on. Answers can be wrong — check before you quit anything.
White and blue in light mode, black and blue in dark mode — one look across windows and popovers, switched with one click or following the system.
Fans and sleep
| Fan mode | What it does |
|---|---|
| Auto | Hands the fans back to macOS |
| Cool | Holds them at 60% between minimum and maximum speed |
| Max | Full speed |
| Custom | A slider, anywhere in the fan's range |
In Custom, the fans are handed back to macOS the moment the CPU reaches the safety temperature (95 °C by default). Quitting XStats, or the app crashing, restores automatic control. Running with the lid closed switches itself off on battery below a floor you choose.
Both need system privileges, provided by a small helper registered with SMAppService and
approved once in System Settings → General → Login Items. The helper offers a fixed set of
operations — set a fan's target speed, return fans to auto, toggle pmset disablesleep,
flush the DNS cache, purge memory — and never runs arbitrary commands. It checks the
caller's code signature, restores fans and sleep when the app disconnects, and after an
unclean exit restores them at the next boot.
Cleanup
- What it scans. App caches, logs and crash reports, browser caches (Chrome, Edge, Brave, Arc, Firefox, Safari), Xcode DerivedData, simulator caches, the npm cache, Xcode archives, unfinished downloads, installers and the Trash.
- Review first. Sizes by category, every rule expandable to its items, a second click to confirm. Caches and logs are deleted outright so the space comes back at once; downloads go to the Trash. One switch sends everything to the Trash instead.
- Safety. Only allow-listed folders are ever touched. Keychains, password managers,
VPNs, cookies and history are off limits. Caches of running apps are skipped, browsers must
be quit first, and every item is checked again right before it goes. Each action is logged
to
~/Library/Logs/XStats/cleanup.log. - Maintenance. Flush the DNS cache and purge memory — through the helper if it is installed, otherwise after a one-time administrator prompt.
Uninstaller and startup items
- Uninstall apps: lists third-party apps in Applications with their size. Pick one or drop an app in, and XStats finds what it left in your Library — app data, caches, preferences, sandbox containers, saved window state, logs, web data and login items — each of which you can untick. Confirming moves everything, app included, to the Trash (restorable) and removes its Dock icon. Matching is by bundle identifier and same-named folders only; built-in and Apple apps are not listed, and running apps must be quit first.
- Startup items: lists LaunchAgents for the current user and all users, plus system LaunchDaemons, with the owning app, executable, whether it runs at login or is kept alive, and whether it is running, loaded or disabled. Your own items can be disabled or re-enabled in place (recorded in launchd's disabled list and unloaded, no files deleted); the rest are read-only, with a shortcut to the system Login Items settings.
Your data
Metrics come from the kernel (host_processor_info, host_statistics64, sysctl), IOKit and the
SMC on your own Mac. Preferences live in the app's user defaults and contain nothing personal.
There is no analytics and no telemetry.
Every feature that touches the network can be turned off — the first two in Settings → Network, the update check in Settings → About:
- Public IP: when you open network details, one request to Cloudflare
1.1.1.1(ipify as fallback) for your public address, cached for 10 minutes. Location, ASN, network type and the cleanliness score come fromcleanip.io, queried directly from each Mac with nothing but the public address and never through our servers; a result is kept for a week unless the address changes or you refresh. - Connection probe: an ICMP ping to the target you pick (Cloudflare, Google, Alibaba Cloud, Tencent or your router) once a second while network details are open (every 10 seconds in the background), only while the network item is in the menu bar or network details are open.
- Update check: at launch and once a day, the app reads a version manifest from getopenstats.com — the manifest only. When a new version is out it asks; nothing installs without your click.
WebDAV sync sends only preferences to your configured server. It excludes monitoring data, history and WebDAV credentials.
WebDAV settings sync
- Create a directory on your WebDAV server, then open Settings → Settings Sync.
- Enter the directory's HTTPS URL, username and password (or app password), then save. Basic authentication and a valid TLS certificate are required; redirects are rejected, so use the final directory URL.
- Upload Local Settings writes xstats-settings.json. Confirming the upload replaces any previous file; changes from other Macs are not merged.
- On another Mac, configure the same directory and select Download and Apply. The backup is checked before you confirm applying it to local preferences.
Sync is manual; nothing is uploaded at startup, on wake or when a setting changes. Configure each Mac separately. Passwords are stored only in the local Keychain. The JSON backup is not encrypted at rest by XStats, so use a private WebDAV directory. The first download returns “no remote settings file” until you upload once. Files over 1 MB, invalid backups and unsupported versions are rejected without changing local settings. Legacy GitHub/Google/Apple login and the old account backend have been removed. Settings sync only needs your WebDAV server.
Process explanations run entirely on device through Apple Intelligence; process details never leave the Mac.
Build & run
Requires macOS 14+, Xcode 26 or later (CommandLineTools alone lacks the SwiftUI macro plugins) and XcodeGen.
brew install xcodegen
make run # generate the project, build Release, install and launch
make install # build Release, install into /Applications and launch
make test # unit tests: metrics, SMC decoding, cleanup safety
make open # generate the project and open it in Xcode
The app is a menu-bar agent, so there is little to screenshot. Render the surfaces with live data instead:
/Applications/XStats.app/Contents/MacOS/XStats --snapshot ./snapshots
To measure the panel while it is open, launch with
--show-panel, which opens the panel and pins it.
After editing CHANGELOG.md, run python3 Scripts/sync_changelog.py to refresh the recent
updates above and the activity chart.
Distribution
Developer ID only, not the App Store — the sandbox forbids talking to the SMC, reading other apps' caches and installing a privileged helper, which is most of the feature set.
| What you have | What others get |
|---|---|
| Nothing | Ad-hoc signature — runs on your Mac only. Others see "XStats is damaged". |
| Developer ID certificate | Hardened runtime. Others see "Apple cannot check it for malicious software". |
| Certificate + notarization | Gatekeeper accepts it — the normal "downloaded from the internet" prompt. |
make build and make install sign with the first Developer ID Application certificate in
the keychain and fall back to ad-hoc without one. The helper reads its own team at run time
and accepts only callers signed by the same team.
Ad-hoc builds cannot install or use the privileged helper, so fan and lid-closed controls are unavailable. Maintenance operations with an existing fallback can request one-time administrator authorization. Startup unregisters previously registered ad-hoc helpers. Team-signed builds unregister and upgrade helpers older than protocol 5 before allowing privileged calls.
make release # sign, notarize, staple, build the DMG and a Homebrew cask
NOTARY_PROFILE=XStats make release # use another notarytool keychain profile
SKIP_NOTARIZE=1 make release # an unnotarized DMG for testing on this Mac only
Scripts/release.sh refuses to produce a DMG that Gatekeeper would still reject.
Architecture
Packages/XStatsKit/Sources/SMC— SMC reads and writes, fan control, temperature sensor discovery.Packages/XStatsKit/Sources/Metrics— samplers for CPU, memory, network, GPU, disk, battery, processes and sensors, andMetricsHub, which samples only what is on screen.Packages/XStatsKit/Sources/Cleaner— cleanup rules, the safety guard, scanning and cleaning.Packages/XStatsKit/Sources/HelperShared— the XPC protocol and maintenance commands.Packages/XStatsKit/Sources/WebDAVSync— manual WebDAV sync and Keychain password storage.Packages/XStatsKit/Sources/XStatsUI— design tokens, the panel, settings and the menu-bar renderer.Helper/— the privileged helper and its launchd plist.App/— the entry point.
More in ARCHITECTURE.md. Every change to the app is logged, dated, in CHANGELOG.md.
Acknowledgements
XStats builds on these open-source projects. Thank you.
| Project | Author | License | What XStats took |
|---|---|---|---|
| OpenStats | GiantAccel, LLC | MIT | The upstream project on which XStats is based; thank you for making it open source |
| Stats | Serhiy Mytrovtsiy | MIT | SMC access, the Apple Silicon fan unlock sequence and the menu-bar mini widget metrics |
| Mole | tw93 | GPL-3.0 | Which folders are worth cleaning and which must never be touched; the cleaner is an independent Swift implementation and contains no Mole code |
| QuotaBar | GiantAccel, LLC | MIT | This README's layout, the changelog sync and the activity chart |
Details in ThirdPartyNotices.md.
XStats is an independent third-party app. It is not affiliated with, endorsed by, or sponsored by Apple or any other company it mentions. Their names and logos belong to their respective owners.
License
New XStats code and modifications are licensed under AGPL-3.0-or-later. See LICENSE and licensing scope and contribution requirements (Chinese).
Upstream OpenStats code retains its MIT license and copyright notice. Other third-party terms are listed in ThirdPartyNotices.md.











