VM management · File transfer

File transfer (host ↔ guest)

Five working paths to move files between the host Mac and a guest VM, plus what's deliberately blocked. Pick by your network mode, your guest OS, and how much you trust the workload.

Quick picker

Your situationUse
Ongoing dev work, lots of file editsVirtioFS shared folder (rw)
One file, scripted, AI agentsecvf vm copy-to
Setup scripts → router VMScripts USB
Arbitrary bulk files, one-timeVirtual USB disk
Guest has SSH and you have a route to itscp
One file, no shared anythingHTTP one-shot
Malware sample, untrusted guestVirtual USB disk (read-only)
Pull a file out of a compromised guestsecvf vm copy-from
Default stance: SecVF VMs have no shared filesystem with the host by default. This is intentional — it keeps the analysis surface clean. Every method below is opt-in and explicit.

1. VirtioFS shared folder

The Apple Virtualization framework's VZVirtioFileSystemDevice is a host directory mounted into the guest as a real filesystem. High throughput, page-cache-aware, transparent to most software running in the guest.

When to use

Best for ongoing work — editing source from the host while building inside the guest, watching files change live, anything where the cost of attach/detach matters. Not for one-shot deliveries.

Enabling

  1. Stop the VM.
  2. VM Library → right-click the VM → Edit configuration…Shared folders tab.
  3. Click +, pick the host directory you want to share.
  4. Choose Read-only or Read-write. The default is read-only; flip to read-write only when you need the guest to write back.
  5. Give the share a tag — this is the name the guest will see (e.g. workspace, downloads).
  6. Save. Start the VM.

Mounting inside the guest

Linux:

# macOS 14+ Linux guests get virtiofs via the framework's standard driver.
# Modern kernels include the module already.

sudo mkdir -p /mnt/workspace
sudo mount -t virtiofs workspace /mnt/workspace        # tag = workspace

# Persist across reboots — add to /etc/fstab:
echo "workspace  /mnt/workspace  virtiofs  defaults  0  0" \
  | sudo tee -a /etc/fstab

macOS guest: the framework auto-presents the share. It appears under /Volumes/<tag>.

Windows guest: Microsoft's WinFsp + a virtiofs driver are required. Less mature than the Linux path; expect more friction.

Performance

OperationLatency (M2 Pro, Linux guest)
4 KB read (cached on host)~3 µs
4 KB read (cold, NVMe)~30 µs
Large file streaming read~1.5 GB/s
Small file batch (1000 × 4KB)~5 ms total

For comparison, scp over the virtual switch is roughly 50–100× slower for small-file workloads.

Security considerations

VirtioFS is a real conduit into your host. Things to know:

  • Owner of the inodes is the host. The guest can't change permissions or ownership in ways that escape the share's scope.
  • Read-only is enforced at the framework level, not in the guest. A compromised guest can't write to a RO share.
  • Symlinks within the share resolve inside it. A guest can't ln -s /Users/me/.ssh /mnt/workspace/secrets and read your keys through it.
  • Don't share /, /Users, or /Volumes. SecVF will refuse those paths at the framework boundary, but other directories above an SSH key or a wallet are still bad choices.
  • For malware: never enable a read-write VirtioFS share to a malware-analysis VM. Don't even share read-only unless you understand exactly what's inside the share — a clever sample can stage a payload there that you might later open from the host.

2. secvf vm copy-to / copy-from

One-shot transfer commands. Programmatic, scriptable, sensible defaults.

secvf vm copy-to   <vm> <host-path> <guest-path>
secvf vm copy-from <vm> <guest-path> <host-path>

Examples

# Push a malware sample into a sandbox VM
secvf vm copy-to malware-sandbox ./sample.bin /tmp/sample.bin

# Pull a guest's syslog out for analysis
secvf vm copy-from kali-router /var/log/syslog ./router-syslog.txt

# Push an entire directory (tar over the wire)
secvf vm copy-to dev-vm ./project /home/dev/project

# Use --json for scripting
secvf vm copy-to my-vm ./pcap.bin /tmp/p.bin --json
# → {"success": true, "data": {"bytes": 12482, "duration_ms": 47}}

What's underneath

The command transparently picks the best available transport:

  1. VirtioFS if a share is already enabled — drops the file into the shared directory, then runs mv inside the guest. Fastest.
  2. vsock for AI sandbox VMs — uses the same channel as secvf vm exec, ~150 µs round-trip.
  3. scp fallback if the guest has SSH and is reachable on the virtual switch.
  4. Virtual USB as last resort — creates an ephemeral disk, attaches, mounts inside guest, copies, ejects, deletes.

The chosen transport is in the --json output's data.transport field if you need to know which one ran.

Use this when

  • You're scripting against the CLI (AI agents, batch detonation, CI).
  • You want one transfer without ongoing share setup.
  • You're not sure which transport will work — let the CLI pick.

3. Scripts USB

The dedicated pattern for shipping setup scripts into a guest. Read-only by design.

From the GUI

VM Library → right-click VM → Mount Scripts USB…

SecVF builds a fresh DMG containing scripts/ from the repo and attaches it. Inside the guest:

sudo mount /dev/sdb1 /mnt
ls /mnt
sudo bash /mnt/kali-router-setup.sh

From the CLI

secvf usb create-virtual --name secvf-scripts --size 64 \
                         --format dmg --source ./scripts \
  && secvf usb mount secvf-scripts --to kali-router

Use this when

You're delivering the standard SecVF helper scripts (router setup, FakeNet, etc.). For the canonical workflow see Scripts reference.

4. Virtual USB disk (arbitrary contents)

Like the Scripts USB pattern but you choose what's inside. Great for shipping arbitrary files into an isolated VM without enabling VirtioFS.

# Build it
secvf usb create-virtual \
    --name secvf-payload \
    --size 256 \                   # MB — sized to fit your files
    --format dmg \                 # or iso for read-only-by-construction
    --source ./files-to-ship/

# Attach
secvf usb mount secvf-payload --to malware-sandbox

# (inside guest)
sudo mkdir -p /mnt/secvf
sudo mount /dev/sdb1 /mnt/secvf
ls /mnt/secvf
# ... use them ...
sudo umount /mnt/secvf

# (back on host)
secvf usb eject secvf-payload

Going the other way (guest → host)

Create the virtual USB read-write, attach, write files inside the guest, eject. Then on the host:

hdiutil attach ~/.avf/VirtualUSB/secvf-payload.dmg
# Read files from the mount point
ls /Volumes/secvf-payload
hdiutil detach /Volumes/secvf-payload

Use this when

  • One-time bulk file transfer (dozens of MB to a couple GB).
  • You want a controlled, finite, ejectable conduit — better security stance than VirtioFS for analysis VMs.
  • Guest OS has no SSH and you don't want to install one.
For malware analysis: use read-only ISO format, not DMG. The guest can't write back. Once the sample's seen it, the file is the same. Treat the virtual USB as a one-way drop.

5. scp / sftp over the virtual network

If the guest has SSH and you have a route to it, plain old scp works.

Route availability per network mode

Network modeCan the host scp into the guest?
NATYes. The framework's NAT subnet is reachable from the host (typically 192.168.<n>.0/24). Find the guest IP from inside the guest (ip addr) or from the VM's status panel.
Virtual NetworkOnly if the host is also on the switch (rare — see macos-network-setup.sh).
Router VMYes, if the host can reach the router VM's WAN side. Usually scp directly to the router; for lab guests behind the router, hop via the router.
FakeNetSame as Router VM. The sinkholing only affects outbound from the lab — your host-to-router scp still works.

Setting up SSH in the guest

# Linux guest, one-time
sudo apt update && sudo apt install -y openssh-server
sudo systemctl enable --now ssh
ip addr show                            # note the IP

# (on host) verify reachability
ping <guest-ip>
ssh user@<guest-ip>

Push / pull files

# Push a single file
scp ./local.txt user@<guest-ip>:/home/user/

# Push a directory recursively
scp -r ./project user@<guest-ip>:/home/user/

# Pull a file
scp user@<guest-ip>:/var/log/syslog ./

# Interactive sftp
sftp user@<guest-ip>

Use this when

You're already comfortable with SSH workflows, the guest is one you're going to interact with regularly, and you have or are willing to set up SSH key auth.

Don't enable SSH inside a malware sandbox VM. If the sample compromises the SSH daemon, that's now a foothold from the lab into wherever your host can reach. Use other methods.

6. HTTP one-shot

Sometimes the fastest path is Python's http.server in one place and curl in the other.

Host → guest

# On host
cd /path/to/files
python3 -m http.server 8080

# On guest (Linux), in any directory
curl -O http://<host-ip>:8080/file.txt
# or
wget http://<host-ip>:8080/file.txt

Guest → host

# On guest
cd /path/in/guest
python3 -m http.server 8080

# On host
curl -O http://<guest-ip>:8080/file.txt

Use this when

  • You want zero ceremony — no shares to enable, no SSH to install, no USB to build.
  • One file or a small handful.
  • Both sides have Python or wget/curl available.
Reachability still applies. The guest must be able to reach the host's IP. NAT and Router VM modes generally allow this; Virtual Network mode does not unless you've explicitly bridged the host onto the switch.

What's NOT supported (and why)

Clipboard sharing

The Apple Virtualization framework exposes clipboard sharing only for macOS guests in recent versions. SecVF doesn't expose it yet — it's on the roadmap. Workaround: paste into a temp file on the host, transfer with any method above.

Drag and drop

Some VM apps (Parallels, VMware Fusion) implement drag-and-drop as a UI affordance on top of their own guest tools. SecVF stays close to the Apple framework, which doesn't ship guest tools — so no drag-drop. Workaround: VirtioFS share is the closest equivalent.

Mounting a host directory directly into the guest's filesystem table

You can't do this without VirtioFS being configured. There's no "magic" auto-mount.

SMB or NFS from the guest to the host

Technically possible — set up an SMB server on macOS or run NFS — but we don't recommend it. The protocols are noisy, the auth is finicky, and you've now opened a network listener on the host. Use VirtioFS instead.

Picking a path for malware analysis

The order, from most-to-least-recommended for analysis workloads:

  1. Read-only virtual USB ISO. Finite contents you chose. Sample sees the file, can't write back, USB ejects clean. Best.
  2. secvf vm copy-to with the virtual-USB transport. Same shape, scripted.
  3. HTTP one-shot from a host-controlled server — you choose what's served. Sample sees one file, no back-channel.
  4. Read-only VirtioFS share with a tightly-scoped directory — acceptable if you understand the share's contents.
  5. NOT read-write VirtioFS. Sample can plant payloads in the host-visible directory.
  6. NOT SSH inside the sample VM. SSH daemon is attack surface.

Troubleshooting

SymptomLikely causeFix
VirtioFS share doesn't show up in guestShare added but VM wasn't restartedStop VM, start again — share devices attach at boot
mount: unknown filesystem type 'virtiofs'Old Linux kernel without the virtiofs moduleUse a guest with kernel ≥5.4 (every modern distro)
secvf vm copy-to says "no transport available"No VirtioFS share, no SSH in guest, USB creation failedCheck disk space; check guest is running
scp times outWrong network mode — host can't reach guestSee the route availability table above
HTTP transfer fails between NAT VMsNAT'd VMs are isolated from each otherSwitch to Virtual Network or Router VM mode
Guest can't write to VirtioFS shareShare is read-onlyEdit configuration → flip to read-write (only if you trust the guest)
secvf vm copy-from on AI sandbox truncates large filevsock buffer limit on huge transfersMount a virtual USB rw, write inside, eject, read host-side