VM management · USB devices
USB devices & passthrough
Two related capabilities: attach a physical USB device (stick, hardware key, debugger) to a guest, and ship a virtual USB disk full of files (the Scripts USB pattern). Both ride the same Apple Virtualization framework primitives — but with different security implications.
On this page
Two flavours of USB
| Physical passthrough | Virtual disk | |
|---|---|---|
| Source | An actual USB device on your Mac | A file SecVF generates on demand |
| Backed by | VZUSBMassStorageDeviceConfiguration + IOKit handoff | A .dmg or .iso presented as USB mass storage |
| Lifetime | While the device is attached & the VM running | Until you eject and delete |
| Visible to guest | As real USB hardware (matching VID/PID) | As a generic USB mass storage device |
| Use cases | Hardware keys, ICS dongles, hardware debuggers, USB-connected radios | Shipping scripts, ISO transfers, throwaway file exchange |
| Security risk | Higher — real hardware, real driver surface | Lower — controlled bytes you assembled |
Physical USB passthrough
How it works
SecVF enumerates connected USB devices via IOKit. When you mount a device to a VM, the framework detaches it from the host kernel and re-attaches it to the guest's virtual USB controller. The guest sees the device's real VID/PID and any vendor-specific descriptors — so device-driver matching inside the guest works the same as on bare metal.
┌─────────────────────────────────────────────┐
│ host macOS │
│ IOKit ──→ SecVF (USBManagerBridge) │
│ │ │
│ ▼ mount │
│ VZUSBMassStorageDeviceConfiguration │
│ │ │
│ ▼ │
│ guest's virtio-usb controller │
│ │ │
│ ▼ │
│ guest kernel sees: vendor=0x0951 model=DTSE9│
└─────────────────────────────────────────────┘
From the GUI
- Plug in the device.
- VM Library → select the target VM → right-click → Attach USB device…
- SecVF lists every host-visible USB device with vendor, model, and current status. Pick one. Click Attach.
- The device disappears from the host (Finder ejects it) and appears inside the guest. The guest's automount flow takes over from there.
- To detach: VM Library → Eject USB, or right-click the device row in the Active USB sidebar.
From the CLI
# Enumerate
secvf usb list
# Attach a device to a VM (use the device's name or ID from `list`)
secvf usb mount "Kingston DT 32GB" --to malware-sandbox
# Eject
secvf usb eject "Kingston DT 32GB"
Constraints (from the framework)
- Mass storage only for some host macOS versions. The Virtualization framework's USB support is biased toward storage; HID and serial passthrough have caveats.
- Single guest at a time. A device is owned by one VM until ejected — you can't share a USB stick between two running guests.
- Boot devices excluded. The host's own boot disk and primary storage are never offered for passthrough.
- The framework owns the USB controller. SecVF doesn't expose raw bus-level access; if your tool wants the underlying USB transactions, you'd need to do that inside the guest's USB stack.
Virtual USB disks (the Scripts pattern)
What it is
A file (DMG or ISO) presented to the guest as a USB mass-storage device. SecVF builds it on demand, populates it from a host directory you choose, and attaches it to the VM. The guest sees a generic USB disk it can mount, read, and (if you configure it that way) write.
The Scripts USB workflow
The most common use is shipping setup scripts into a Kali router VM:
- VM Library → right-click the Kali VM → Mount Scripts USB…
- SecVF builds a fresh DMG containing the contents of
scripts/from the repo and attaches it. - Inside the guest:
sudo mount /dev/sdb1 /mnt && cd /mnt && sudo bash kali-router-setup.sh. - Eject from the VM Library when done. The DMG file is cleaned up.
From the CLI
secvf usb create-virtual \
--name secvf-scripts \
--size 64 \ # MB
--format dmg \ # or iso
--source ./scripts # host directory to include
# Then attach
secvf usb mount secvf-scripts --to kali-router
What the guest sees
An HFS+ volume on /dev/sdb1 (or similar). Mounts the same way any USB stick would. Read-only or read-write depending on the format you chose at creation time.
CLI surface
Full reference is on the CLI page. Quick:
secvf usb list # all devices, physical + virtual
secvf usb list --include-virtual # explicitly include virtual
secvf usb list --json # for scripting
secvf usb mount <device> --to <vm> # attach
secvf usb eject <device> # detach
secvf usb create-virtual \ # build a virtual disk
--name <name> --size <MB> \
--format dmg|iso \
[--source <host-dir>] # populate from a dir
Use cases
Shipping scripts into a guest
The Scripts USB pattern. Cleanest way to deliver a directory of files to a VM that has no shared folders by default. See Scripts reference for what to ship.
Exfil-resistant file transfer
You want to give a guest a binary to detonate, but you don't want shared folders open (which would give the malware writable host paths). A read-only virtual USB is a perfect drop — guest reads, malware runs, USB ejects, transfer complete.
Hardware key for testing on a guest
YubiKey, FIDO2 token, hardware wallet. Plug into host, attach to guest, the guest sees the device's real descriptors and any vendor driver in the guest matches. Useful for testing how malware interacts with hardware tokens (some samples ignore them; others try to harvest).
ICS / SCADA dongles
Industrial protocol dongles (Modbus over USB, Profibus adapters) often only have Windows drivers. Pass through to a Windows guest for testing without needing a dedicated Windows host.
USB-connected radios & SDRs
HackRF, BladeRF, RTL-SDR — pass through to a Kali guest with GNU Radio or SDR# for wireless analysis. The SDR sees the host's USB controller and operates normally inside the guest.
Hardware debuggers
JTAG, SWD probes — pass through to embedded-target reverse engineering VMs.
Capturing USB activity from malware
This one's asymmetric: if you attach a USB stick to a malware sandbox VM, you can see what files the malware tries to write or modify on it. Use a freshly-wiped, isolated USB stick for this. Don't pass through your everyday work USB.
Hardware keys & smart cards
Specific notes for the FIDO2 / smart card use case:
- HID-based keys (YubiKey OTP, FIDO2) — pass through works on macOS 14+ with the framework's HID support. The guest needs a matching driver/PCSC stack.
- CCID smart cards — pass through works; the guest needs
pcscd+openscfor the reader to show up properly. - U2F — works, but the U2F binding includes the host's app identifier. If you're testing browser-based U2F in the guest, the binding is per-guest-browser, not transferable.
Inside the guest: mounting
Linux guest
# See what's there
lsblk
dmesg | tail -20 # confirm the device showed up
# Mount (usually /dev/sdb1, but check lsblk output)
sudo mkdir -p /mnt/secvf
sudo mount /dev/sdb1 /mnt/secvf
# When done
sudo umount /mnt/secvf
Windows guest
Windows auto-mounts USB mass storage. The drive appears as a new letter. Use Disk Management for finer control.
macOS guest
Auto-mounts via DiskArbitration, just like on host. Appears in Finder sidebar.
Security considerations
USB is a real attack surface. Things to weigh:
- Hostile guest with attached USB: the guest's USB stack can attempt to fuzz the host's view of the device. The framework mediates, so the blast radius is contained to the framework's USB implementation — but it's a non-zero surface.
- Hostile USB device: if you plug in an untrusted USB stick and pass it to a hardened VM for analysis, that's good practice. But the device touches your host briefly during the attach — Bad-USB-style firmware attacks could fire there.
- Persistence via USB: a clever sample might write a payload to the USB and hope you re-attach it elsewhere. Treat any USB that's been touched by a malware VM as contaminated.
- USB descriptors leak host info: the device passes through with its real VID/PID. Don't pass through a serial-numbered device you'd rather not associate with the analysis (e.g. your personal YubiKey).
What the framework doesn't do
For honesty:
- No raw USB bus exposure. If your tool needs to manipulate USB transactions (libusb at the lowest level), you need to do that inside the guest.
- No USB hub passthrough. You attach individual devices, not the entire hub-and-everything-on-it.
- No "USB redirector"-style network passthrough. Devices on remote machines can't be attached as if local.
- No granular permission per device. Either the framework allows passthrough or it doesn't. There's no per-device entitlement.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
Device shows in usb list but Attach is disabled | Device is currently mounted on the host (Finder, Disk Utility) | Eject from host first, then attach to VM |
| Attach succeeds but guest doesn't see anything | Guest USB driver missing / stack not loaded | Check dmesg in guest; install relevant kernel modules |
| Eject hangs | Guest has the device busy (open file, mount) | Unmount inside the guest first: sudo umount /mnt/... |
| HID device works on host, not in guest | HID passthrough has stricter framework rules | Try mass-storage class only; HID may need a guest USB driver SecVF can't influence |
| Virtual USB creation fails: "image too large" | Exceeded host's available disk | Use a smaller --size, or free up host disk |
| Virtual USB shows up but is empty | Source dir was empty or unreadable when creation ran | Verify --source exists and has files; re-run |