Detection · Containment breakout

Containment breakout

SecVF has four isolation boundaries: the hypervisor, the network policy, the filesystem, and the IPC layer. This page documents what indicators suggest each boundary may have been crossed, what SecVF automatically does when it detects one, and the operational procedure for responding when something looks wrong.

If you're reading this because of an active alert, scroll to Response procedure first. The triage flow gets you to "VM paused, evidence preserved" in under 90 seconds. Read the rest after.

What containment means in SecVF

"Containment" is the property that whatever runs inside a SecVF guest VM stays there. The guest can compute, write files inside its disk image, send traffic on its virtual NIC, talk to authorized channels — but it cannot read the host's files, cannot intercept host network traffic, cannot read host memory, cannot run host code.

That property is maintained by four distinct boundaries acting in concert. Each has its own technology, its own failure modes, and its own indicators. A "containment breakout" means one of those four has been (or appears to have been) crossed.

Honest disclaimer: a successful breakout almost certainly means a hypervisor 0-day. They are rare, but they exist. SecVF's job in that scenario is to log enough to tell you it happened and preserve evidence for analysis. We don't claim to prevent determined attackers from breaking out — we claim to detect and trace.

The four boundary layers

┌─────────────────────────────────────────────────────────────┐
│  Host (macOS — your laptop)                                  │
│  ┌────────────────────────────────────────────────────────┐ │
│  │  Layer 1: Apple Virtualization framework (HYPERVISOR)   │ │
│  │  ┌────────────────────────────────────────────────────┐ │ │
│  │  │  Guest VM kernel (untrusted)                        │ │ │
│  │  │   ┌────────┐    ┌────────────┐                      │ │ │
│  │  │   │ guest  │    │ guest      │                      │ │ │
│  │  │   │ user-  │    │ kernel     │                      │ │ │
│  │  │   │ space  │    │ space      │                      │ │ │
│  │  │   └────┬───┘    └─────┬──────┘                      │ │ │
│  │  │        │              │                              │ │ │
│  │  │  Layer 4: IPC (vsock, VirtioFS, USB) ← can talk here│ │ │
│  │  │  Layer 3: Filesystem (bundle is the disk image)     │ │ │
│  │  │  Layer 2: Network (virtual NIC → virtual switch)    │ │ │
│  │  └────────────────────────────────────────────────────┘ │ │
│  └────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘

Working outward: a guest must defeat layer 1 (hypervisor) to reach the host directly. It can attempt to abuse layers 2-4 to influence the host (network attack, filesystem trickery, IPC abuse), but those abuses don't get arbitrary host execution unless they cascade into a layer-1 break.

Layer 1: Hypervisor

The Apple Virtualization framework runs the guest VM. Memory isolation, CPU isolation, and instruction-emulation are enforced in hardware (EPT/SLAT page tables) and by Apple's kernel code. A breach of this layer = arbitrary code execution on the host.

Indicators

IndicatorLikelihood it's realWhat it would look like
SecVF process crashes immediately after guest activityMedium — could be a benign framework bugSecVF.app exits without user action, crash report in ~/Library/Logs/DiagnosticReports/
Guest VM kernel panics in unusual patterns (repeated, same offset)Low (most kernel panics are benign), but worth notingVisible in the VM display window, also in ~/.avf/logs/security-*.log as severity CRITICAL
Unexpected child processes from SecVF.appHigh signal — SecVF only spawns tshark + secvf-cliIn Activity Monitor: SecVF tree has processes besides itself, tshark, the framework's helper
Host kernel panic during VM operationVery high signalSystem reboots; /Library/Logs/DiagnosticReports/Kernel-*.ips
Anomalous resource exhaustion (memory, file descriptors)Medium — could be a benign leakSpikes in Activity Monitor

SecVF's view

SecVF observes the VZ framework via standard callbacks. Things it logs at this layer:

  • vm-lifecycle.crashed — guest VZ instance crashed unexpectedly
  • vm-lifecycle.unexpected-stop — VM transitioned to stopped without the user requesting it
  • vm-lifecycle.framework-error — VZ returned an error code SecVF didn't expect

Layer 2: Network

Every guest connects to the virtual switch (or directly to a framework-managed NAT, in NAT mode). The switch is SecVF code in the host process. Network mode determines what the guest can reach:

  • NAT: guest reaches the internet via host NAT. Host can't be reached.
  • Virtual: guest reaches only other VMs on the switch. No uplink. Host not on the switch.
  • Router: guest reaches its gateway VM (Kali router), which forwards to the internet.
  • FakeNet: as Router, but the gateway sinkholes everything.

Indicators

IndicatorWhat it means
Outbound traffic from a Virtual-mode VMEither misconfiguration or a guest finding a path off the switch. Investigate immediately.
MAC address moves between ports rapidlyARP spoofing attempt by a guest, or a misbehaving driver
Switch packet drops sustained for >5 minutesEither capture queue saturation (benign) or malformed frames being rejected (suspicious)
Frames with the host's MAC address on a non-host portGuest impersonation attempt
Connections to 10.0.100.1 from lab guests (Router mode)Normal traffic, but if it's flooding or includes management-port targeting, investigate
Outbound HTTP/HTTPS from a VM that's supposed to be air-gappedLab misconfig or guest bridging out somehow
DNS queries inside FakeNet sinkhole not all resolving to 10.0.100.1Guest is using a DNS resolver outside the lab

SecVF's view

  • network.switch.drop — frame dropped (with reason)
  • network.virtual-mode.unexpected-egress — Virtual-mode VM tried to send to a non-virtual address (CRITICAL)
  • network.mac-table.flap — MAC moved between ports rapidly
  • network.frame.malformed — frame failed parsing in the switch

Layer 3: Filesystem

The guest's view of "disk" is the disk image inside its bundle. SecVF (and only SecVF) writes to anything in ~/.avf/<family>/<vm>.bundle/ except the disk image — and the guest can only write to the disk image through the virtual block device. Any other file appearing in the bundle, NVRAM mutating outside boot, or FSEvents firing for paths the guest shouldn't be able to reach = filesystem-boundary anomaly.

Indicators

IndicatorWhat it means
File appears in <vm>.bundle/ that SecVF didn't writeExternal process or boundary violation. SecVF logs this as file.unexpected
NVRAM file modified outside of bootNVRAM should only change during VM boot/start. Mid-run changes are anomalous.
Disk image size grows faster than expectedUsually benign (heavy I/O in guest), but worth a glance if it spikes 10× normal
FSEvents fires for the bundle directory at idleBackground process is touching the bundle. Spotlight, Time Machine, or a containment indicator
Bundle disappears or files within get deletedExternal actor or user error
Permissions on bundle files changeSecVF preserves permissions; changes mean something outside SecVF wrote

SecVF's view

SecVF uses FSEvents to watch each running VM's bundle directory. Events logged:

  • fsevents.file.unexpected — file present that SecVF didn't write (CRITICAL)
  • fsevents.nvram.mutation — NVRAM changed outside boot window
  • fsevents.bundle.deleted-while-running — bundle dir disappeared
  • fsevents.disk-image.size-spike — disk image grew faster than expected

Layer 4: IPC (vsock, VirtioFS, USB)

The guest has authorized communication channels — but each one is bounded. Crossing these bounds (e.g. sending an oversized vsock message, creating a symlink in a VirtioFS share that points outside) is a containment indicator.

Indicators

ChannelIndicator
vsockOversized messages, non-conforming protocol frames, attempts to connect to non-SecVF ports
VirtioFSSymlinks inside the share pointing to paths outside the share root, attempts to access dotfile entries the host hides, mass file creation
USBGuest attempting to write to a read-only USB, USB descriptor anomalies, devices appearing in guest that the host didn't pass through

SecVF's view

  • vsock.message.oversized — guest tried to send a message exceeding the protocol limit
  • vsock.protocol.violation — vsock message didn't parse as expected
  • virtiofs.symlink.escape-attempt — symlink target points outside the share (refused by framework, logged here)
  • virtiofs.access.unauthorized — guest tried to read a path the share metadata says should be blocked
  • usb.descriptor.anomaly — USB device descriptor changed mid-session

SecVF's automatic responses

When SecVF observes any of the above indicators, what it does automatically (in addition to logging):

SeverityAutomatic action
INFORecorded only. No UI notification.
WARNINGRecorded. Shown in Security Logs window (1) with yellow indicator.
CRITICALRecorded. Window indicator goes red. System sound plays. Event also written to os_log at error level.
EMERGENCYAll of the above + Dock badge updates + system notification + cannot be hidden from the window even if filter is set higher.

Critical to note: SecVF does NOT automatically stop the VM or take destructive action. Preserving state for forensics is more important than reflexive containment. The user decides what to do.

Detection in the SIEM

If you're running the SIEM stack, the Containment dashboard surfaces all four layers' indicators in one view:

  • Four per-layer stat panels at the top (red on ≥1 event)
  • Stacked timeseries showing event volume by layer over time
  • Live tail of all CRITICAL+EMERGENCY events from the four boundary subsystems
  • Embedded response procedure panel (same as the section below)

Five Sigma rules pre-compile into Grafana alerts that fire when boundary indicators trigger:

  • EMERGENCY event detected (any layer)
  • ISO checksum mismatch
  • Sustained switch packet drops
  • Unexpected file in VM bundle
  • VirtioFS symlink escape

See SIEM § Alerts for how to wire those to actual notifications (email, Slack, Apple system notification).

Response procedure

When something fires, walk this in order. The first three steps should take under 90 seconds.

1. Pause the suspect VM — don't stop it

Stopping kills the VM's RAM state. Pausing preserves everything. SecVF → VM Library → right-click the VM → Pause, or P while the VM window is focused.

# Or from the CLI:
secvf vm pause <vm-name>

2. Snapshot the bundle

Duplicate the bundle while paused so you have a forensic copy that won't get touched as you investigate:

secvf vm snapshot <vm-name> --as <vm-name>-incident-$(date +%s)
# APFS CoW — takes <5 ms, no disk space cost until divergence

3. Export logs and audit trail

INCIDENT_DIR=~/incident-$(date +%F-%H%M%S)
mkdir -p "$INCIDENT_DIR"

# All audit logs around the incident
cp ~/.avf/logs/security-$(date +%F).log     "$INCIDENT_DIR/"
cp ~/.avf/logs/security-$(date -d yesterday +%F).log "$INCIDENT_DIR/" 2>/dev/null
cp ~/.avf/logs/error-audit.log              "$INCIDENT_DIR/"
cp ~/.avf/logs/network-$(date +%F).log      "$INCIDENT_DIR/"

# If AI sandbox is involved, the session bundle has its own log
cp -r ~/.avf/AISandbox/sessions             "$INCIDENT_DIR/ai-sandbox-sessions"

# Recent captures (Suricata may have flagged them)
cp -r ~/.avf/Captures                       "$INCIDENT_DIR/captures"

# macOS unified log slice for the last hour
log show --predicate 'subsystem == "com.DaxxSec.SecVF"' --last 1h \
  > "$INCIDENT_DIR/oslog.txt"

# Console / SecVF crash reports
cp -r ~/Library/Logs/DiagnosticReports/SecVF*.ips "$INCIDENT_DIR/" 2>/dev/null

echo "Incident bundle: $INCIDENT_DIR"
tar -czf "$INCIDENT_DIR.tar.gz" -C "$(dirname $INCIDENT_DIR)" "$(basename $INCIDENT_DIR)"

You now have everything needed for offline analysis. The paused VM bundle, the snapshot, the audit logs, the captures.

4. Investigate

Open the incident-bundle logs. Walk these questions:

  1. Which boundary? Look at the subsystem field of the firing events.
  2. What was the trigger? The event + data fields tell you specifically what SecVF saw.
  3. What was the guest doing in the seconds before? Cross-reference the network log + Suricata alerts + YARA matches at the timestamp.
  4. What's the blast radius? What other VMs were on the same switch? Any of them paused too?
  5. Was the host reached? Look at macOS unified log around the time. Anything anomalous in kernel / SecVF entries?

5. Decide

  • Benign (most common): a misconfiguration, a buggy driver, Spotlight scanning the bundle. Log it, fix the cause, resume the VM.
  • Suspicious: can't explain the indicator. Keep the snapshot, keep the incident bundle, file a GitHub issue with the (redacted) logs. Don't destroy the VM yet — there may be follow-on analysis.
  • Confirmed boundary break: see After an incident. Treat the host as compromised until proven otherwise.

6. Resume or destroy

If benign: secvf vm resume <vm-name> and continue.

If keeping the original VM is undesirable: stop it (secvf vm stop --force), delete it (secvf vm delete --force), and replace with the snapshot. The snapshot itself remains untouched.

Severity × cause × action matrix

SeverityLikely causeAction
WARNING + switch dropsCapture queue saturatingTighten BPF filter; raise buffer size
WARNING + AI session orphanSecVF crashed mid-sessionDelete stale bundle; re-run base provisioning if frequent
WARNING + Suricata C2 alertMalware sample doing its job in the labExpected; harvest IOCs
WARNING + YARA matchSample matched a ruleExpected; cross-ref VirusTotal
CRITICAL + ISO checksum mismatchUpstream mirror anomaly or network corruptionRetry; if persistent, supply-chain concern
CRITICAL + file.unexpected in bundleExternal process touched bundle (Spotlight, Time Machine, user edit)Investigate; usually benign
CRITICAL + VirtioFS symlink escapeGuest aware of VirtioFS share, probingContainment indicator — pause, snapshot, investigate
CRITICAL + Virtual-mode unexpected egressMisconfiguration or guest finding bridgePause immediately; verify network mode
EMERGENCY (any)SecVF judged this as a real boundary breakFull response procedure (above)
SecVF process crash + host kernel panic concurrentPossible framework 0-dayDisconnect from network. Full host audit. File with Apple Security + SecVF security.

After an incident

If you suspect the host may be compromised

  1. Disconnect from network. Pull WiFi, unplug Ethernet. Don't shut down — preserving RAM state matters if you do forensics later.
  2. Don't restart. Restarting wipes RAM evidence and may trigger persistence mechanisms.
  3. Run a baseline check from a known-good source (a separate Mac, a live USB):
    • spctl --status (Gatekeeper)
    • csrutil status (SIP)
    • kmutil showloaded (loaded kexts — should be only Apple-signed)
    • launchctl list | grep -v com.apple (third-party launch agents)
    • Read-only mount the disk from a live USB and run a malware scanner
  4. If anything looks off: back up the data you care about to read-only media, then nuke and pave. macOS recovery → Erase disk → reinstall. Don't restore from a Time Machine backup that includes the compromise window.

Disclosure

If you think you've found a real hypervisor or framework vulnerability:

  • Apple Product Security (the framework is theirs)
  • security@daxxsec.tech (SecVF's contribution to the chain)
  • Include: macOS version, chip generation, SecVF version + commit, the incident bundle, reproduction steps if known

If you reproduce a benign cause

File a doc bug — we want to add it to the Troubleshooting page so the next person doesn't panic. PRs welcome.