I have done the following
Steps to reproduce
- Create a custom type conforming to
Containerization.Interface.
- Supply an IPv4 address and return
nil from ipv4Gateway:
struct GatewaylessInterface: Interface, VZInterface {
let base: any Interface & VZInterface
var ipv4Address: CIDRv4 { base.ipv4Address }
var ipv4Gateway: IPv4Address? { nil }
var macAddress: MACAddress? { base.macAddress }
var mtu: UInt32 { base.mtu }
func device() throws -> VZVirtioNetworkDeviceConfiguration { try base.device() }
}
- Start a
LinuxContainer whose first and only interface is this gatewayless interface.
- Inside the guest, run:
ip -4 route show
ip route get 1.1.1.1
The issue is deterministic in a real Virtualization.framework Linux microVM.
The 0.33.1 public contract documents ipv4Gateway as “The IP address for the default route, or nil for no default route”:
https://github.com/apple/containerization/blob/0.33.1/Sources/Containerization/Interface.swift#L25-L26
However, LinuxContainer calls routeAddDefault(name:ipv4Gateway:) with nil for the first interface:
https://github.com/apple/containerization/blob/0.33.1/Sources/Containerization/LinuxContainer.swift#L631-L654
Current main retains the same semantic behavior through setupInterface: when both gateways are nil it logs “no gateway” and still calls routeAddDefault:
https://github.com/apple/containerization/blob/main/Sources/Containerization/VirtualMachineAgent%2BInterface.swift#L76-L82
Current behavior
The guest receives an on-link default route even though ipv4Gateway is nil:
default dev eth0 scope link
172.16.0.0/24 dev eth0 scope link src 172.16.0.3
Consequently, route lookup treats arbitrary external destinations as directly reachable on eth0 and attempts neighbor resolution on that link.
This does not necessarily provide external connectivity when the backing attachment is private and has no uplink, but it contradicts the public Interface contract and prevents callers from creating a first interface with no default route.
Expected behavior
When ipv4Gateway is nil, LinuxContainer should configure the IPv4 address and link route without installing an IPv4 default route. IPv4 and IPv6 default-route installation should follow their respective optional gateway values.
Environment
- OS: macOS 26.5.2 (25F84)
- Xcode: 26.6 (17F113)
- Swift: Apple Swift 6.3.1
- Containerization: 0.33.1
- Architecture: Apple silicon / arm64
Relevant log output
default dev eth0 scope link
172.16.0.0/24 dev eth0 scope link src 172.16.0.3
Code of Conduct
I have done the following
mainSteps to reproduce
Containerization.Interface.nilfromipv4Gateway:LinuxContainerwhose first and only interface is this gatewayless interface.The issue is deterministic in a real Virtualization.framework Linux microVM.
The 0.33.1 public contract documents
ipv4Gatewayas “The IP address for the default route, or nil for no default route”:https://github.com/apple/containerization/blob/0.33.1/Sources/Containerization/Interface.swift#L25-L26
However,
LinuxContainercallsrouteAddDefault(name:ipv4Gateway:)withnilfor the first interface:https://github.com/apple/containerization/blob/0.33.1/Sources/Containerization/LinuxContainer.swift#L631-L654
Current
mainretains the same semantic behavior throughsetupInterface: when both gateways are nil it logs “no gateway” and still callsrouteAddDefault:https://github.com/apple/containerization/blob/main/Sources/Containerization/VirtualMachineAgent%2BInterface.swift#L76-L82
Current behavior
The guest receives an on-link default route even though
ipv4Gatewayis nil:Consequently, route lookup treats arbitrary external destinations as directly reachable on
eth0and attempts neighbor resolution on that link.This does not necessarily provide external connectivity when the backing attachment is private and has no uplink, but it contradicts the public
Interfacecontract and prevents callers from creating a first interface with no default route.Expected behavior
When
ipv4Gatewayis nil,LinuxContainershould configure the IPv4 address and link route without installing an IPv4 default route. IPv4 and IPv6 default-route installation should follow their respective optional gateway values.Environment
Relevant log output
Code of Conduct