Technology — Networking

flashnet: a privileged helper the VMM never needs to be.

flashvmm never holds CAP_NET_ADMIN — not "drops it after setup," never has it at all. A separate process, flashnet, does every piece of host-side network mutation, then hands off to an unprivileged flash run.

flowchart LR
  A["flashnet --mode {bridge|nat|routed}
[--uplink IFACE]"] --> B["Create persistent TAP device"] B --> C{mode} C -->|bridge| D["Guest joins physical L2 segment
workload's own DHCP configures it"] C -->|nat| E["Per-VM nftables NAT table
fixed 192.168.253.2/30"] C -->|routed| F["Real DHCP lease via proxy-ARP"] D --> G["fork()"] E --> G F --> G G --> H["drop ALL capabilities
in the child"] H --> I["exec flash run ... --nic TAP"] I --> J["flashvmm: CAP_NET_ADMIN
never held, ever"]
All host-side network mutation — netlink, nftables NAT, DHCP — happens natively inside flashnet, never by shelling out to another privileged tool.

Three modes, three real network models

Bridge

Linux only, and --uplink is required. The guest joins the physical L2 segment directly; the workload's own DHCP client configures its address — the FlashVM looks like any other host on the network.

NAT

A per-VM nftables NAT table gives the guest its own /30, derived from --vm-id, translated to the host's uplink — the default-route interface unless --uplink names one. Isolated by default, reachable via explicit port mapping. macOS and Windows run the same command over a per-VM user-mode NAT; on every OS the guest reports net: eth0=<addr> gw ok dns <resolver>.

Routed

The guest gets a real DHCP lease via proxy-ARP — routable, without joining the physical L2 segment directly.

Why this split matters

The single most dangerous capability a compromised VMM process could have is direct control over host networking. FlashVMM's architecture makes that impossible by construction, not by convention: the process that actually runs guest code has never, at any point in its lifetime, held CAP_NET_ADMIN. The capability lives only in flashnet, and only until the fork — after which the child that becomes flashvmm has already dropped everything. A vulnerability in the VMM's virtio-net implementation cannot escalate into host network control, because the process running that code was never capable of it.