# VM mode
Source: https://docs.privacycommand.privacykey.org/vm-mode

Run the analysis inside a disposable macOS VM, and ship the observations back to your Mac.

For a bundle you genuinely don't trust, running it on your own machine is the
wrong move — even under observation. VM mode moves the execution into a
disposable macOS guest and streams the results back.

## The shape of it

privacycommand ships a **guest agent** into a macOS VM. The agent runs the same
observation work inside the guest and sends what it sees back to the host across
the VM boundary, using a small zero-dependency wire protocol shared by both
sides.

Your Mac ends up with the report. The guest is what actually ran the app, and
you can throw it away afterwards.

Tested against [VirtualBuddy](https://github.com/insidegui/VirtualBuddy),
[UTM](https://mac.getutm.app), and Parallels.

## When to use it

- **Anything you'd hesitate to double-click.** Unsigned bundles, things from a
  download aggregator, a `.dmg` a stranger sent you.
- **Software that fights inspection.** If static analysis flagged anti-analysis
  signals, assume it may behave differently when it thinks it's being watched —
  and note that some of those checks specifically look for VMs, so a guest can
  change behaviour too.
- **Anything that installs persistence.** Login items, agents, and daemons land
  in the guest rather than on your Mac, and vanish with the snapshot.

## Setting it up

You need a macOS VM you can install into. privacycommand packages the agent for
you, but not all of this is automated — it's worth knowing which parts aren't
before you start.

**Step 1: Build a guest and snapshot it clean**

Install macOS in your VM tool of choice and take a snapshot before anything
else touches it. That snapshot is what makes runs disposable.

**Step 2: Build the installer disk image**

**Settings → VM agent → Build installer disk image.** It packages
`privacycommand-guest` together with its LaunchAgent plist and an
`Install.command` into a small `.dmg` under
`~/Library/Application Support/privacycommand/`. About thirty seconds the
first time. No toolchain needed — a release build ships the agent binary
inside itself.

The same panel detects VirtualBuddy, UTM, Parallels and VMware Fusion. For
the first three it lists the VMs each one knows about and can start one for
you. VMware Fusion exposes no automation surface privacycommand can rely on,
so it is detected and then left alone — start that VM yourself.

**Step 3: Get the image into the guest — by hand**

Drag the `.dmg` onto the running VM's window. Every supported front-end
accepts the drop and mounts it inside the guest.

This is the step privacycommand can't do for you: none of the VM tools
exposes a public way for an outside app to attach a disk image to a running
guest.

**Step 4: Install the agent inside the guest**

In the guest, open the mounted volume and double-click `Install.command`.
It asks for the guest's admin password, installs the LaunchAgent, and
confirms the agent is listening on **TCP 49374** (override with `--port`).

**Step 5: Connect from the host**

There is no discovery — nothing on your Mac goes looking for the guest.
Read the guest's address from inside it with `ifconfig en0 | grep inet`,
then type that IP and the port into **Settings → VM agent** and click
**Test connection**. **Run in VM** stays disabled until the agent answers.

**Step 6: Revert when you're done**

Roll the guest back to the clean snapshot. Anything the app installed goes
with it.

Getting the app you want to inspect into the guest is also yours to do — drag,
AirDrop or `scp` it across — and you give privacycommand its path *inside* the
VM, because the host can't enumerate the guest's filesystem.

The protocol and the agent's internals are documented under
[Guest agent](https://docs.privacycommand.privacykey.org/develop/guest-agent).

## Limits worth knowing

**VM detection is common.** Plenty of software — DRM especially — behaves
differently in a guest. A clean run in a VM is not proof of a clean run on
bare metal.

**Apple Silicon guests run Apple Silicon macOS.** You can't audit an Intel-only
build in an ARM guest without Rosetta in the picture, which changes what you're
observing.

**Performance costs coverage.** Guests are slower, and a slow run tends to be a
shorter run, which means fewer exercised code paths. Give it longer than you
would on the host.
