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.

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:

InputSourceMitigation
VM disk image bytesGuest OSPassed unmodified to VZ; framework parses, not SecVF.
Ethernet framesGuest NICParsed in VirtualNetworkSwitch — Swift, bounds-checked, fuzz-tested.
vsock messagesAI sandbox guestLength-prefixed JSON; max message size enforced; rejects malformed before parse.
ISO file contentsUpstream mirrorSHA-256 verified before mount; bytes never inspected by SecVF.
IPSW file contentsApple CDNDomain allowlist + TLS 1.2+; restoration is by VZ framework.
metadata.jsonUser-editableCodable decode; unknown fields rejected per schemaVersion.
tshark output (JSON-EK)tshark subprocessLine-delimited; bounded per-line size; oversize lines truncated + logged.
USB device descriptorsUSB stackRead-only enumeration via macOS frameworks; not parsed by SecVF.
CLI argsUser shellSwift-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

SeverityWhat it meansExample
INFONormal operation. Worth recording, not worth alerting."Switch frame forwarded", "ISO download started"
WARNINGUnexpected but recoverable. Worth a glance."Switch queue at 80% — packet drops imminent if rate sustains"
CRITICALSomething broke. Needs operator attention."ISO checksum mismatch — file deleted"
EMERGENCYSecurity 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.

ConcernDirect-download buildApp Store build (sandboxed)
VM bundle location~/.avf/App sandbox container: ~/Library/Containers/com.DaxxSec.SecVF/Data/avf/
Packet captureShells out to tsharkIn-process libpcap with a temporary-exception entitlement scoped to the loopback + virtual switch
Helper scripts (Scripts USB)Directly bundled in app resourcesSame — bundled resources are readable inside the sandbox
tshark detectionSearches $PATHDisabled — sandbox forbids arbitrary subprocess exec
Audit log path~/.avf/logs/Sandbox container Logs/ dir (accessible via Console.app)
Code baseSame. 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.