v0.3.1 — P0 safety: wrong-disk wipe fix + Manage Disk crash fix
Mactoy v0.3.1 — P0 safety release: wrong-disk wipe + Manage Disk crash
Critical safety release. A user reported in issue #1 that v0.3.0 wiped the wrong external disk: they had two USB drives plugged in, selected disk5, confirmed disk5, and Mactoy wrote disk6. Root cause analysis confirmed the bug exists in every shipped Mactoy version (v0.1.0 through v0.3.0) — those releases have all been retroactively marked as prereleases on GitHub. v0.3.1 is the first release that's safe to install.
This release also fixes a SwiftUI crash on macOS 26 (Sequoia / Tahoe) when clicking the Manage Disk tab — three users hit it on M4 Studio / MBP M4 / Air M4 hardware.
What was broken in v0.3.0 and earlier
When you clicked Install Ventoy, Mactoy showed a confirmation sheet with the disk's name and size. You clicked Confirm. Internally, Mactoy then re-read the selected disk at the moment of execution rather than using the disk you'd just confirmed.
If — between you clicking Install and clicking Confirm — the disk-enumeration poll ran (it runs every 2 seconds) AND your originally-selected disk momentarily dropped off the bus (USB-C hub re-enumerating, sleep/wake, even normal power-management churn), applyDiskList cleared the selection and snapped it to the next available disk. The install then ran on that disk, not the one you confirmed.
The reporter had a SATA SSD at disk5 (the one they wanted to flash) and a USB-C SSD at disk6 (one with personal data). Mactoy wiped disk6.
v0.3.1 — six-layer iron-clad targeting defense
Every layer must pass for any byte to hit /dev/rdisk*.
-
Confirmation captures full disk fingerprint.
EraseConfirmationcarries the completeDiskTarget— bsdName, sizeInBytes, mediaName, isExternal, isRemovable. Treated as authoritative from the moment you click Install onward. -
Selection frozen during confirmation.
applyDiskListrefuses to mutateselectedDiskBSDwhile a confirmation sheet is open. The disk list still updates; the selection does not. -
run()takes the captured target as an explicit parameter. No more re-readingselectedDiskfrom insiderun().confirmRun()threads the captured pair through; the helper-poll auto-resume path uses a storedpendingRunTargetto survive the helper-approval gap so the same disk is targeted on both first call and post-approval resume. -
App-side re-verification. Right before handing the plan to the daemon,
run()callsDiskInfo.probe(bsdName:)and asserts the live disk's fingerprint matches the captured one (via the newDiskTarget.fingerprintMismatch(against:)helper). Any mismatch — size, mediaName, external/removable flags, BSD name — aborts with a clear error sheet and no XPC call is made. -
Daemon-side re-verification.
VentoyDriver.executeFreshInstall,VentoyDriver.executeUpdate, andRawImageDriver.executeALL re-probe the disk viaDiskInfo.probebefore opening/dev/rdisk*. The daemon is the last line of defense; it does not trust the app to have got the targeting right. -
BSD-name guard at execution. Even if the rest of the fingerprint coincidentally matches a different physical drive that landed at the same
disk<N>slot, the captured BSD name must still match the currentselectedDiskBSDorrun()refuses with a "selection drifted" error.
The new DiskTarget.fingerprintMismatch(against:) helper centralizes the comparison. It's covered by 8 unit tests in DiskTargetFingerprintTests.swift, including the exact "RTL9210B-CG → SSD 840 PRO Seri" scenario from the user's report.
Manage Disk crash fix
Three users in issue #1 reported crashes when clicking the Manage Disk tab — stack traces showed swift_release → swift_arrayDestroy → HVStack.updateCache SIGSEGV inside SwiftUI itself.
Root cause: ContentView wrapped every panel in a ScrollView. ManageDiskPanel contains a List. List inside ScrollView is a known SwiftUI footgun — both manage their own scroll geometry and fight each other; on macOS 26 the fight surfaces as a use-after-free in the layout cache.
v0.3.1 branches the wrapper in ContentView: Manage Disk renders without the outer ScrollView (the inner List manages its own vertical overflow). The other panels (Install Ventoy / Update Ventoy / Flash Image) keep their ScrollView wrappers — they don't contain a List.
Install
# Download Mactoy-0.3.1.dmg from the release assets.
open Mactoy-0.3.1.dmg
# Drag Mactoy.app into /Applications.Apple-notarized. If you have any prior Mactoy version installed, please update to v0.3.1 immediately — every version before this one has the wrong-disk bug.
Verification
swift build -c releaseclean for bothMactoyandmactoyd.- Universal binary verified via
lipo -info(x86_64 arm64on both products). - 38/38 tests pass (
swift test) — 8 new fingerprint tests added. - Independent code review of the diff before tagging.
Known limitations
- The original wrong-disk race is verified to be closed by static analysis and parser-level tests. Reproducing the exact disk-arbitration churn timing in an automated test would require a simulated DiskArbitration harness — that test rig is on the v0.4 roadmap. If you can reproduce a wrong-disk wipe on v0.3.1, please file a P0 issue immediately with
log show --predicate 'subsystem == "com.mactoy"' --last 1houtput. - All releases v0.1.0 through v0.3.0 remain available as prereleases for forensics. Do not install them.
SHA256 of Mactoy-0.3.1.dmg is published below the release assets.