Skip to content

[Bug]: Two NAT networks can be assigned the same bridge ifnet; teardown of one silently destroys the other's egress until helper restart #2051

Description

@paulcdejean

I have done the following

  • I have searched the existing issues
  • If possible, I've reproduced the issue using the 'main' branch of this project

Steps to reproduce

container system stop
container system start
container network delete debug-network-a
container network delete debug-network-b
container network create debug-network-a
container network create debug-network-b
container run --rm --network debug-network-b docker.io/alpine:latest true && sleep 2 && echo "Network B has claimed bridge100 and released it"
container run --rm --detach --name a1 --network debug-network-a docker.io/alpine:latest sleep 60 && sleep 2 && echo "Victim a1 up on network A (bridge100)"
container exec a1 sh -c 'nc -zw3 1.1.1.1 443 && echo "Egress working"'
container run --rm --detach --name b1 --network debug-network-b docker.io/alpine:latest sleep 60 && sleep 2 && echo "Aggressor b1 up on network B"
ifconfig | grep -c '^bridge1'
container kill b1 && sleep 2 && echo "Oh no, the bridge is deleted"
container exec a1 sh -c 'nc -zw3 1.1.1.1 443 && echo "Egress working" || echo "Egress broken"'
container run --rm --network debug-network-a docker.io/alpine:latest sh -c 'nc -zw3 1.1.1.1 443 && echo Egress working || echo Egress still b

Problem description

On macOS 26, each NAT network's kernel bridge (bridge100, bridge101, …) is created when the network's first attachment starts and destroyed when its last attachment stops. The unit number appears to be assigned at a network's first instantiation — lowest unit free at that moment — and reused for that network object's lifetime.

If network B's first instantiation happens while network A's bridge is down, both network objects are assigned the same unit. The next time both networks have live attachments at once, they share a single recycled ifnet — the kernel logs bridge100 detaching and bridge100: attached with N suspended link-layer multicast membership(s) in the same millisecond. When either network's last container then exits, the shared ifnet is destroyed out from under the other network's live attachments.

From that moment the surviving network is permanently broken: new containers still get vmenet interfaces, but with no bridge and no gateway they have no connectivity at all. container-network-vmnet logs nothing at persisted levels, the network object never re-creates its bridge, and only restarting the helper (or container system) recovers. Day to day this presents as "container networking randomly dies after working for hours" — the trigger is an unlucky interleaving of container lifetimes across two NAT networks, so it strikes intermittently on any multi-network setup.

Environment

- OS: macOS 26.5.2 (25F84)
- Xcode: Xcode 26.5 (17F42)
- Container: container CLI version 1.0.0 (build: release, commit: ee848e3)

Code of Conduct

  • I agree to follow this project's Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions