Reference · Security model
Security model
A precise statement of what SecVF defends against, what it doesn't, where the trust boundaries are, and how the audit trail proves what happened. Read this before you trust it with anything you can't lose.
On this page
Assumptions
The threat model only makes sense given these baseline assumptions:
- The host is yours. You control admin access. Nobody else has shell, screen sharing, or kernel debugger attached.
- The macOS install is current. You apply security updates. SecVF inherits the kernel's mitigations; an unpatched host weakens the whole stack.
- Apple Virtualization framework is the trust anchor. If Apple's hypervisor has a 0-day that lets a guest escape, you lose. SecVF can't do better than its substrate.
- The CPU honors its mitigations. Speculative-execution mitigations are present and not disabled by boot flags. Apple Silicon's L1/L2 partitioning between secure enclaves is intact.
- You don't disable SIP or run as root. System Integrity Protection on the host gives the AVF process baseline protections SecVF relies on.
If you violate any of these — say, you turned off SIP for kernel development — the threat model degrades accordingly, and that's on you to evaluate.
Trust boundaries
┌─────────────────────────────────────────────────────────────┐
│ YOU (host operator) │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ macOS (host kernel + AVF + SIP) │ │ ← trust anchor
│ │ ┌──────────────────────────────────────────────────┐ │ │
│ │ │ SecVF.app (your code, open source) │ │ │
│ │ │ ┌────────────────────────────────────────────┐ │ │ │
│ │ │ │ Hypervisor (AVF, hardware-enforced) │ │ │ │
│ │ │ │ ┌──────────────────────────────────────┐ │ │ │ │
│ │ │ │ │ Guest VM (UNTRUSTED — malware here) │ │ │ │ │
│ │ │ │ └──────────────────────────────────────┘ │ │ │ │
│ │ │ └────────────────────────────────────────────┘ │ │ │
│ │ └──────────────────────────────────────────────────┘ │ │
│ └────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
Going outward, each layer trusts the next. The fundamental boundary is between SecVF (host code) and the guest VM (untrusted): everything inside the guest is assumed hostile, and the hypervisor + framework are what keep it contained.
Defended against
Userland escape from guest
Userland processes inside a guest have access to the guest kernel and its devices. They have no path to the host's filesystem or processes — no shared folders are mounted by default, no virtio-9p or VirtioFS shares without explicit configuration, no host-side helper agent running in the guest.
Kernel exploits in guest
Even root inside a compromised guest sees only:
- Its own (synthetic) hardware: NICs, disk, console, vsock device
- Its NVRAM and EFI variables (scoped to the bundle)
- The virtual switch port the framework gave it
To reach the host, the guest needs a hypervisor exploit — escaping the EPT/SLAT page tables — not a kernel exploit. Bar is much higher.
Network exfiltration
In Virtual Network mode there's literally no uplink. In Router-VM mode the gateway is your own Kali instance; in FakeNet mode the gateway sinkholes everything. NAT mode is the only one that lets a guest reach the public internet — and you choose that explicitly, per VM.
Tampered ISOs / IPSWs
See Download provenance below. Mismatches are deleted before the framework ever sees them.
Filesystem tampering of bundles
SecVF's VMSecurityMonitor uses FSEvents on each bundle directory. Disk-image growth past expected rates, NVRAM mutation outside boot, sidecar files appearing in the bundle — all logged as INFO or WARNING. Tamper attempts surface within seconds.
Information loss for forensics
Every typed error, every security event, every ISO verification — appended to ~/.avf/logs/ as line-delimited JSON. Append-only by design; SecVF doesn't truncate. See Audit trail.
Not defended against
Be honest about the limits. SecVF is good but it is not magic.
Apple Virtualization framework 0-days
If VZVirtualMachine has an escape bug, the guest can reach the host. SecVF can do nothing about this. Mitigations: keep macOS updated, watch Apple's CVE disclosures.
Hardware side-channels
Spectre-style speculative leaks, ROWHAMMER variants, cache-timing attacks across cores — these target the silicon, not the software. Apple Silicon has mitigations, but they're imperfect and ongoing.
Compromise of the host operator
If an attacker has admin on your Mac, they can attach a debugger to SecVF, read raw VM disk images, dump memory, or just replace the SecVF binary. The threat model assumes the operator is trusted.
Visual social engineering from the guest
The guest controls its display. A malicious guest can render anything that looks like macOS UI — including fake "system password" prompts. Don't enter sensitive credentials in the VM window thinking it's a host dialog.
Compromised dependencies
Swift Package Manager fetches dependencies (one, at the time of writing: swift-argument-parser) by Git URL. If apple/swift-argument-parser is ever compromised upstream, SecVF inherits whatever they ship. Mitigation: audit Package.resolved per release, pin to specific commit SHAs in addition to versions.
Targeted insider attack
If the user — you — is the threat (e.g. you're being coerced), no software can save you. SecVF can't distinguish your malicious instructions from your benign ones.
Attack surface inventory
An honest list of every place hostile input enters SecVF's process:
| Input | Source | Mitigation |
|---|---|---|
| VM disk image bytes | Guest OS | Passed unmodified to VZ; framework parses, not SecVF. |
| Ethernet frames | Guest NIC | Parsed in VirtualNetworkSwitch — Swift, bounds-checked, fuzz-tested. |
| vsock messages | AI sandbox guest | Length-prefixed JSON; max message size enforced; rejects malformed before parse. |
| ISO file contents | Upstream mirror | SHA-256 verified before mount; bytes never inspected by SecVF. |
| IPSW file contents | Apple CDN | Domain allowlist + TLS 1.2+; restoration is by VZ framework. |
| metadata.json | User-editable | Codable decode; unknown fields rejected per schemaVersion. |
| tshark output (JSON-EK) | tshark subprocess | Line-delimited; bounded per-line size; oversize lines truncated + logged. |
| USB device descriptors | USB stack | Read-only enumeration via macOS frameworks; not parsed by SecVF. |
| CLI args | User shell | Swift-Argument-Parser; well-formed or rejected. |
Download provenance
Two flavours of external download. Both are tightly constrained.
Linux ISOs
Distro metadata is in Resources/distros.json. Each distro entry pins:
- The mirror hostname (e.g.
cdimage.debian.org) - A URL template for the ISO
- A URL template for the checksum file (
SHA256SUMS)
Versions are discovered live (the mirror's directory listing or release-info file is parsed), but the hostnames are baked in. Downloads from anywhere else are refused at the URLSession level — SecVF's domain whitelist is enforced in ISOCacheManager.swift before the request ever fires.
The flow:
1. Resolve URL via distros.json template
2. Verify hostname matches the pinned mirror
3. Download checksum file (HTTPS, TLS 1.2+)
4. Download ISO (HTTPS, TLS 1.2+)
5. Compute SHA-256 of downloaded ISO
6. Compare against checksum file
7. ┌── match: move to ~/.avf/ISOCache/<distro>-<version>.iso
└── mismatch: delete + raise CRITICAL event in audit log
macOS IPSWs
Apple's IPSW URLs (returned by their software-catalog API) are validated against a hardcoded allowlist of *.cdn-apple.com hostnames in MacOSVMInstaller.swift. Anything else is rejected.
The framework's own restore process validates IPSW signature internally — SecVF doesn't duplicate that, but it does fence the inputs: the IPSW file must (1) come from a permitted hostname, (2) match the .ipsw extension, (3) succeed Apple's signature check inside VZMacOSInstaller.
Audit trail format
Two log streams.
~/.avf/logs/security-YYYY-MM-DD.log
Daily-rotated, line-delimited JSON. One event per line, each event self-contained:
{"ts":"2026-05-10T14:32:01.234Z","severity":"INFO","subsystem":"iso-cache","event":"download.started","vm":null,"data":{"url":"https://cdimage.debian.org/...","host":"cdimage.debian.org"}}
{"ts":"2026-05-10T14:32:45.890Z","severity":"INFO","subsystem":"iso-cache","event":"download.verified","vm":null,"data":{"file":"debian-12.iso","sha256":"abc..."}}
{"ts":"2026-05-10T14:33:02.115Z","severity":"WARNING","subsystem":"network","event":"switch.drop","vm":"ubuntu-malware","data":{"reason":"queue-saturation","drop_count":17}}
{"ts":"2026-05-10T14:33:30.601Z","severity":"CRITICAL","subsystem":"iso-cache","event":"checksum.mismatch","vm":null,"data":{"file":"untrusted.iso","expected":"...","got":"..."}}
~/.avf/logs/error-audit.log
Append-only typed-error stream from SecVFError. Every error raised, with its category, localized description, and (if available) recovery suggestion:
{"ts":"...","category":"vm-config","code":"missing-disk-image","message":"Disk.img not found in bundle","recovery":"Try recreating the VM, or restore from a snapshot","stack":"..."}
Both files are append-only from SecVF's side — there's no truncation API, no log-clear button. To rotate, copy to archive and delete; SecVF will create a new file on next write.
Severity ladder
| Severity | What it means | Example |
|---|---|---|
| INFO | Normal operation. Worth recording, not worth alerting. | "Switch frame forwarded", "ISO download started" |
| WARNING | Unexpected but recoverable. Worth a glance. | "Switch queue at 80% — packet drops imminent if rate sustains" |
| CRITICAL | Something broke. Needs operator attention. | "ISO checksum mismatch — file deleted" |
| EMERGENCY | Security boundary violated. Stop and investigate. | "Unexpected file appeared in VM bundle directory while VM was stopped" |
Each level is rendered with a distinct colour in the Security Logs panel (⌘⇧1): blue, yellow, red, magenta. EMERGENCY events also play a system sound.
Sandbox-mode adjustments (App Store)
The Mac App Store build runs inside Apple's app sandbox, which forces a few divergences from the direct-download build. The security guarantees are equivalent; the implementation details differ.
| Concern | Direct-download build | App Store build (sandboxed) |
|---|---|---|
| VM bundle location | ~/.avf/ | App sandbox container: ~/Library/Containers/com.DaxxSec.SecVF/Data/avf/ |
| Packet capture | Shells out to tshark | In-process libpcap with a temporary-exception entitlement scoped to the loopback + virtual switch |
| Helper scripts (Scripts USB) | Directly bundled in app resources | Same — bundled resources are readable inside the sandbox |
| tshark detection | Searches $PATH | Disabled — sandbox forbids arbitrary subprocess exec |
| Audit log path | ~/.avf/logs/ | Sandbox container Logs/ dir (accessible via Console.app) |
| Code base | Same. Sandbox adjustments are compile-time flags in a separate fork, not divergent features. | |
Both builds present the same threat model to the guest. The differences only matter when you're working with the host filesystem directly (e.g. backing up a bundle, scripting against the audit log).
Reporting a vulnerability
If you find a security bug:
- Don't open a public issue. Use GitHub Security Advisories: github.com/DaxxSec/SecVF/security/advisories/new
- Or email security@daxxsec.tech — PGP key on the security.txt page.
- Include: affected version (
About SecVF), repro steps, scope (host or guest impact), proposed CVSS. - Acknowledgement within 72 hours; fix or risk-acceptance within 30 days for non-critical, faster for critical.
Public canonical entry-point: /.well-known/security.txt.