Reference · Logging & telemetry

Logging & telemetry

SecVF exposes seven distinct log surfaces, each with its own format and audience. This page documents each one — what data lands there, how to access it, retention semantics, and how to script against it.

The log surface map

┌─ In-app windows ──────────────────────────────────┐  ┌─ On-disk (~/.avf/logs/) ─────────────┐
│  Security Logs       ⌘⇧1                          │  │  security-YYYY-MM-DD.log  (JSONL)   │
│  Network Logs        ⌘⇧2                          │  │  error-audit.log          (JSONL)   │
│  Switch Statistics   ⌘⇧3                          │  │  network-YYYY-MM-DD.log   (text)    │
│  ISO Cache Audit     ⌘⇧4                          │  │  <vm-name>-start-<ts>.log (text)    │
│  Packet Analysis     ⌘⇧P  → its own page          │  │  AISandbox/sessions/<…>/audit.log   │
└───────────────────────────────────────────────────┘  └──────────────────────────────────────┘

Two rules to keep in mind:

  1. The windows are live views of the on-disk logs (with formatting + filters). Quitting SecVF doesn't lose anything — re-open and the windows replay from disk.
  2. On-disk logs are append-only. SecVF never truncates. To rotate, move the file aside — a fresh one is created on next write.

Security Logs window (1)

What it shows

Every event from VMSecurityMonitor, the in-process observer that watches filesystem deltas, resource pressure, and VM lifecycle events. One row per event.

Columns

ColumnDetail
TimeLocal timestamp, millisecond precision.
SeverityINFO / WARNING / CRITICAL / EMERGENCY — color-coded.
VMThe VM the event relates to, or (host) for app-level events.
Subsysteme.g. vm-lifecycle, fsevents, iso-cache, network-switch, ai-sandbox.
EventDotted-namespace event name: boot.requested, file.appeared, checksum.mismatch, etc.
DetailFree-form, often containing paths or counts.

Filters

The top bar accepts:

  • Severity floor — hide everything below the chosen level.
  • VM filter — show only events for one VM.
  • Subsystem filter — drill into a category.
  • Text search — substring match across all columns.

Export

Right-click → Export selection as JSONL. Useful for filing a bug report or shipping to a SIEM.

Network Logs window (2)

What it shows

Every connection observed on the VirtualNetworkSwitch — not full packet decode, just connection-level summaries. Useful for "what talked to what" without the volume of packet capture.

Per-row data

  • Time first seen / last seen
  • Source VM (or external)
  • Destination VM (or external)
  • Protocol (TCP/UDP/ICMP)
  • Source port, destination port
  • Bytes / packets sent and received
  • State (NEW, ESTABLISHED, CLOSED, RESET, TIMEOUT)

When to use vs Packet Analysis

Network Logs is your summary view — answers "did anything weird happen this hour?". Packet Analysis is your microscope — answers "what was in that one suspicious frame?". Use Network Logs to find candidates, Packet Analysis to investigate them.

Switch Statistics window (3)

What it shows

Live operational view of the virtual switch. No history — these are real-time gauges.

Panels

  • Throughput counters — frames forwarded, broadcast, dropped; bytes RX/TX. Updated every second.
  • Port table — each connected VM with its assigned port, MAC address, RX/TX byte counters.
  • MAC learning table — every MAC the switch has learned, mapped to its port, with last-seen age.
  • Security alerts — backpressure events, anomalous MAC moves, dropped-frame floods.

Drop-rate alerts

If Packets Dropped > 0, the capture queue is saturating. This isn't catastrophic — frames are tagged dropped in the security log — but it means tighten the BPF filter or raise the buffer size (see Packet analysis § performance).

ISO Cache Audit window (4)

What it shows

Every ISO download SecVF has performed, with full provenance. One row per file.

Per-row data

ColumnDetail
Distro / VersionWhat was downloaded (Kali 2024.4, Ubuntu 24.04, etc.).
URLFull source URL — verify against the pinned mirror in distros.json.
HostHostname (must be in the allowlist; rejections also logged here).
SHA-256 (expected)From the upstream checksum file.
SHA-256 (actual)Computed locally. Must match.
Result✓ verified, ✗ mismatch (file deleted), ⚠ skipped (already cached).
Bytes / DurationFor perf monitoring.
WhenTimestamp.

This is your provenance audit. If you ever need to prove "the ISO we built that VM from was the legitimate one," this window has the receipt.

Packet Analysis window (P)

Documented in detail on its own page. Briefly: the most-used analysis surface — live capture, Wireshark display filters, protocol stats, hex view, PCAP export.

On-disk: ~/.avf/logs/security-YYYY-MM-DD.log

Format

JSON Lines (one event per line). The Security Logs window reads from this file; you can read it directly with tail -F for live, or jq for offline analysis.

{"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":"..."}}

Rotation

One file per local day. No automatic deletion — files accumulate. Rotate or archive yours periodically.

Useful queries

# Today's critical events
jq -c 'select(.severity == "CRITICAL" or .severity == "EMERGENCY")' \
  ~/.avf/logs/security-$(date +%F).log

# All events for one VM, last 7 days, by severity
jq -c "select(.vm == \"kali-router\")" ~/.avf/logs/security-*.log \
  | jq -s 'group_by(.severity) | map({severity: .[0].severity, count: length})'

# Top subsystems by event volume today
jq -r '.subsystem' ~/.avf/logs/security-$(date +%F).log \
  | sort | uniq -c | sort -rn

On-disk: ~/.avf/logs/error-audit.log

Format

JSON Lines, append-only, no rotation (deliberately — it should be a complete error history).

{"ts":"2026-05-10T14:00:01Z","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":"..."}
{"ts":"2026-05-10T14:01:43Z","category":"network","code":"interface-bind-failed","message":"vmnet attach refused","recovery":"Check System Settings → Network → Firewall isn't blocking SecVF","stack":"..."}

What's in here that's not in the security log

Typed errors with localized recovery suggestions. The security log is event-oriented; this log is error-oriented. They overlap (some events are errors) but they're not the same — investigate both when something breaks.

Categories

Eleven categories defined in SecVFError.swift. Most common when triaging:

  • vm-config — bad metadata.json, bundle structure issues
  • vm-start — boot failed, entitlement, missing IPSW
  • network — switch issues, vmnet failures
  • iso-cache — download failures, hash mismatches
  • permission — entitlement / sandbox failures
  • filesystem — write failures, disk full

On-disk: per-VM start logs

Path

~/.avf/logs/<vm-name>-start-<YYYYMMDD-HHMMSS>.log

What it is

Captured stdout + stderr from the subprocess SecVF spawned for that VM start. When start fails fast — entitlement issue, missing file, VZ error before the framework's own logging kicks in — this is where the real reason hides.

Format

Plain text. Each line a stdout/stderr fragment, with a leading subsystem prefix where SecVF wrote it itself.

When to read

  • A specific VM consistently fails to start while others succeed
  • The Security Logs window says vm-start failed but the audit log doesn't have the underlying reason
  • You need to know what VZ said in the seconds before the error

On-disk: ~/.avf/logs/network-YYYY-MM-DD.log

Format

Human-readable text, one connection event per line. Daily-rotated.

2026-05-10T14:32:01.234Z [switch] port=2 vm=ubuntu-malware mac=52:54:00:d4:e5:f6 NEW tcp 10.0.100.42:38122 -> 10.0.100.1:53
2026-05-10T14:32:01.298Z [switch] port=2 vm=ubuntu-malware  ESTABLISHED tcp 10.0.100.42:38122 -> 10.0.100.1:53 (12 packets, 1.4 KB)
2026-05-10T14:32:15.901Z [switch] port=2 vm=ubuntu-malware  CLOSED tcp 10.0.100.42:38122 -> 10.0.100.1:53 (after 14.6s)

This file backs the Network Logs window. Tail it for live view from the terminal: tail -F ~/.avf/logs/network-$(date +%F).log.

AI sandbox session audit log

Path

~/.avf/AISandbox/sessions/<session-id>.bundle/audit.log

Per-session

Each ephemeral session has its own audit log. Lives inside the session's bundle — destroyed with the bundle. To keep a session's log past destruction, export it via secvf vm exec <session> -- 'cat /var/db/secvf-audit.log' > ./saved.log before destroy.

What's in it

  • session.cloned — APFS clonefile() result, time taken, source base bundle hash
  • session.booted — VZ boot time, VM peer info (vsock CID)
  • vsock.exec — every command run via session.run(), with start/end timestamps and exit code
  • fs.share.mounted — VirtioFS share attached
  • DTrace probe output (selectively) — major file activity, process exec
  • session.destroyed — bundle removal, divergent-block count for telemetry

Format

JSON Lines, same schema as the host security log.

Severity ladder

LevelMeaningWhere it landsDefault visibility
INFONormal operation, worth recording.security-*.log only.Hidden from the window unless floor lowered.
WARNINGUnexpected but recoverable.security-*.log + window.Visible.
CRITICALSomething broke. Needs attention.security-*.log + window + system sound.Visible, color-coded.
EMERGENCYSecurity boundary violated.everywhere + Dock badge + system sound.Cannot be hidden.

The window's default filter is WARNING and above. Drop the floor to see INFO if you're debugging.

Shipping logs to a SIEM

All the on-disk JSONL files are SIEM-friendly. Three patterns:

Tail-and-forward

# Simplest. Use whichever forwarder your SIEM supports.
tail -F ~/.avf/logs/security-*.log | jq -c . \
  | curl -X POST --data-binary @- https://siem.example.com/secvf

Vector / Fluent Bit

# Vector config snippet (vector.toml)
[sources.secvf_security]
type = "file"
include = ["/Users/me/.avf/logs/security-*.log"]
read_from = "end"
[sinks.siem]
type = "http"
inputs = ["secvf_security"]
uri = "https://siem.example.com/ingest"
encoding.codec = "json"

OSLog bridge

If your fleet uses macOS's unified logging system, every SecVF event is also published to os_log under the subsystem com.DaxxSec.SecVF. Standard log stream / log show works:

log stream --predicate 'subsystem == "com.DaxxSec.SecVF"' --info
log show --predicate 'subsystem == "com.DaxxSec.SecVF"' --last 24h --info

Pipe that into your enterprise logging agent (Datadog, Splunk, Crowdstrike, etc.) and SecVF events show up alongside everything else macOS knows about.

Privacy note. SecVF doesn't transmit logs anywhere on its own. If you ship them, you're choosing to. Audit what's in the logs before shipping — VM names, sample paths, and FakeNet captures can be sensitive.