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.
On this page
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.
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
| Indicator | Likelihood it's real | What it would look like |
|---|---|---|
| SecVF process crashes immediately after guest activity | Medium — could be a benign framework bug | SecVF.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 noting | Visible in the VM display window, also in ~/.avf/logs/security-*.log as severity CRITICAL |
| Unexpected child processes from SecVF.app | High signal — SecVF only spawns tshark + secvf-cli | In Activity Monitor: SecVF tree has processes besides itself, tshark, the framework's helper |
| Host kernel panic during VM operation | Very high signal | System reboots; /Library/Logs/DiagnosticReports/Kernel-*.ips |
| Anomalous resource exhaustion (memory, file descriptors) | Medium — could be a benign leak | Spikes 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 unexpectedlyvm-lifecycle.unexpected-stop— VM transitioned to stopped without the user requesting itvm-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
| Indicator | What it means |
|---|---|
| Outbound traffic from a Virtual-mode VM | Either misconfiguration or a guest finding a path off the switch. Investigate immediately. |
| MAC address moves between ports rapidly | ARP spoofing attempt by a guest, or a misbehaving driver |
| Switch packet drops sustained for >5 minutes | Either capture queue saturation (benign) or malformed frames being rejected (suspicious) |
| Frames with the host's MAC address on a non-host port | Guest 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-gapped | Lab misconfig or guest bridging out somehow |
DNS queries inside FakeNet sinkhole not all resolving to 10.0.100.1 | Guest 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 rapidlynetwork.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
| Indicator | What it means |
|---|---|
File appears in <vm>.bundle/ that SecVF didn't write | External process or boundary violation. SecVF logs this as file.unexpected |
| NVRAM file modified outside of boot | NVRAM should only change during VM boot/start. Mid-run changes are anomalous. |
| Disk image size grows faster than expected | Usually benign (heavy I/O in guest), but worth a glance if it spikes 10× normal |
| FSEvents fires for the bundle directory at idle | Background process is touching the bundle. Spotlight, Time Machine, or a containment indicator |
| Bundle disappears or files within get deleted | External actor or user error |
| Permissions on bundle files change | SecVF 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 windowfsevents.bundle.deleted-while-running— bundle dir disappearedfsevents.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
| Channel | Indicator |
|---|---|
| vsock | Oversized messages, non-conforming protocol frames, attempts to connect to non-SecVF ports |
| VirtioFS | Symlinks inside the share pointing to paths outside the share root, attempts to access dotfile entries the host hides, mass file creation |
| USB | Guest 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 limitvsock.protocol.violation— vsock message didn't parse as expectedvirtiofs.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 blockedusb.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):
| Severity | Automatic action |
|---|---|
| INFO | Recorded only. No UI notification. |
| WARNING | Recorded. Shown in Security Logs window (⌘⇧1) with yellow indicator. |
| CRITICAL | Recorded. Window indicator goes red. System sound plays. Event also written to os_log at error level. |
| EMERGENCY | All 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:
- Which boundary? Look at the
subsystemfield of the firing events. - What was the trigger? The
event+datafields tell you specifically what SecVF saw. - What was the guest doing in the seconds before? Cross-reference the network log + Suricata alerts + YARA matches at the timestamp.
- What's the blast radius? What other VMs were on the same switch? Any of them paused too?
- Was the host reached? Look at macOS unified log around the time. Anything anomalous in
kernel/SecVFentries?
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
| Severity | Likely cause | Action |
|---|---|---|
| WARNING + switch drops | Capture queue saturating | Tighten BPF filter; raise buffer size |
| WARNING + AI session orphan | SecVF crashed mid-session | Delete stale bundle; re-run base provisioning if frequent |
| WARNING + Suricata C2 alert | Malware sample doing its job in the lab | Expected; harvest IOCs |
| WARNING + YARA match | Sample matched a rule | Expected; cross-ref VirusTotal |
| CRITICAL + ISO checksum mismatch | Upstream mirror anomaly or network corruption | Retry; if persistent, supply-chain concern |
| CRITICAL + file.unexpected in bundle | External process touched bundle (Spotlight, Time Machine, user edit) | Investigate; usually benign |
| CRITICAL + VirtioFS symlink escape | Guest aware of VirtioFS share, probing | Containment indicator — pause, snapshot, investigate |
| CRITICAL + Virtual-mode unexpected egress | Misconfiguration or guest finding bridge | Pause immediately; verify network mode |
| EMERGENCY (any) | SecVF judged this as a real boundary break | Full response procedure (above) |
| SecVF process crash + host kernel panic concurrent | Possible framework 0-day | Disconnect from network. Full host audit. File with Apple Security + SecVF security. |
After an incident
If you suspect the host may be compromised
- Disconnect from network. Pull WiFi, unplug Ethernet. Don't shut down — preserving RAM state matters if you do forensics later.
- Don't restart. Restarting wipes RAM evidence and may trigger persistence mechanisms.
- 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
- 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.