8000 T124 — Refuse a host-address box with no grant the proxy's address inside the VM · Issue #3047 · gominimal/minimal · GitHub
[go: up one dir, main page]

Skip to content

T124 — Refuse a host-address box with no grant the proxy's address inside the VM #3047

Closed

Description

@norrietaylor

Task

slice size difficulty model who estimated lines
Host-address boxes reach GitHub L unknown ground strongest an agent 720 (300 code, 420 tests)

On a Mac, while a GitHub grant box runs with --network host_ip, a second host-address box with no grant cannot connect to the proxy's address, and the grant box still reaches the proxy's listener.

Layers:

  • spec:
    • docs/specs/24-spec-box-egress-proxy/24-spec-box-egress-proxy.md: BEP-083 gains a sub-requirement that refuses, inside the VM, a resident member that declares no credentialed upstream the proxy's listener and TCP 443, verified by the kernel test below
  • table:
    • scripts/install-host-classifier.sh: a VM-guest-only --proxy-lane ADDR:PORT renders a set bep_lane_leaves of box leaves and an output rule that refuses a new TCP connection from the boxes subtree to ADDR at PORT or 443 unless the socket's leaf is in the set, with the deny chain's counter, log prefix and reject; the helper takes lane-add and lane-remove for that set as it takes add and remove for the UDP 443 set
    • crates/minimald/src/net/classifier.rs: GuestRender carries the proxy's listener, and render_guest_ruleset_over passes --proxy-lane; the cohort records each member's lane bit, a member that declares a credentialed upstream has its own leaf in bep_lane_leaves while resident and stays in its own leaf when the cohort blocks UDP 443, a member that declares none is never listed, and injection_leaf answers none fo 8000 r a lane member
    • crates/minimald/src/main.rs: the guest's render names DEFAULT_SUBNET.box_egress_proxy_address() and PROXY_LISTENER_PORT as the proxy's listener
    • crates/minvmd/tests/guest_classifier_integration.rs: native_ruleset_digest passes the same --proxy-lane, so the guest's loaded table still digests equal to the native render
    • cargo nextest run -p minimald guest_render_refuses_the_proxy_address_outside_the_lane_set
  • cohort:
    • crates/minimald/src/box_actor/host.rs: HostMoves changes the lane set through the helper's new verbs, and join_quic443_cohort passes the record's lane bit to the cohort
    • cargo nextest run -p minimald lane_less_cohort_member_stays_out_of_the_proxy_lane_set
  • kernel:
    • crates/minimald/tests/netns_root_integration.rs: a leg that loads the table rendered with --proxy-lane at a namespace address, places two members in their own leaves with only the first in the lane set, and shows the first's connects to the listener port and to 443 accepted and the second's refused with EHOSTUNREACH, both while the cohort blocks UDP 443 and while it does not
    • crates/minvmd/src/net/egress_gate.rs: the interim paragraph of host_ip_verdict's doc comment goes; the gate logic stays as the lane's host half
    • cargo nextest run -p minimald --run-ignored ignored-only only_the_declaring_cohort_member_reaches_the_proxy_address

Spec text the owner approved, to add under BEP-083 in docs/specs/24-spec-box-egress-proxy/24-spec-box-egress-proxy.md:

  - IF a resident `host_ip` box of a VM host that declares no credentialed upstream opens a TCP connection to the proxy's listener or to the proxy's address on TCP port 443, THEN THE SYSTEM SHALL refuse the connection inside the VM.
    tier:   T0
    verify: cargo nextest run -p minimald --run-ignored ignored-only only_the_declaring_cohort_member_reaches_the_proxy_address

If the VM guest image lacks the quic443-leaf sudo helper, minimald changes the lane set itself through the guest's nft, as it already loads the table with root privilege.

Waits on:

Plan block
### T124 — Refuse a host-address box with no grant the proxy's address inside the VM
  slice: S17
  kind: task
  covers: BEP-083
  size: L
  est: 300 code, 420 tests
  executor: agent
  difficulty: unknown ground
  model: strongest
  diagnostics: inside a `host_ip` box with no grant on a Mac, a TCP connect to the proxy's address on its listener port or on 443 fails at once with "No route to host", while a `host_ip` grant box in the same VM connects; the VM's kernel log carries the classifier's rate-limited "minimal-classifier: refused" line for the refused connect
  observability: one info line per change of the classifier's proxy-lane set names the box id, its leaf and the lane members, as the UDP 443 set's change line does; the table's existing refusal counter counts each refused connect; the host gate's existing debug line for a cohort frame to the proxy's address still names the declaring members
  layers:
    - spec:
      - docs/specs/24-spec-box-egress-proxy/24-spec-box-egress-proxy.md: BEP-083 gains a sub-requirement that refuses, inside the VM, a resident member that declares no credentialed upstream the proxy's listener and TCP 443, verified by the kernel test below
    - table:
      - scripts/install-host-classifier.sh: a VM-guest-only `--proxy-lane ADDR:PORT` renders a set `bep_lane_leaves` of box leaves and an output rule that refuses a new TCP connection from the boxes subtree to ADDR at PORT or 443 unless the socket's leaf is in the set, with the deny chain's counter, log prefix and reject; the helper takes `lane-add` and `lane-remove` for that set as it takes `add` and `remove` for the UDP 443 set
      - crates/minimald/src/net/classifier.rs: `GuestRender` carries the proxy's listener, and `render_guest_ruleset_over` passes `--proxy-lane`; the cohort records each member's lane bit, a member that declares a credentialed upstream has its own leaf in `bep_lane_leaves` while resident and stays in its own leaf when the cohort blocks UDP 443, a member that declares none is never listed, and `injection_leaf` answers none for a lane member
      - crates/minimald/src/main.rs: the guest's render names `DEFAULT_SUBNET.box_egress_proxy_address()` and `PROXY_LISTENER_PORT` as the proxy's listener
      - crates/minvmd/tests/guest_classifier_integration.rs: `native_ruleset_digest` passes the same `--proxy-lane`, so the guest's loaded table still digests equal to the native render
      test: cargo nextest run -p minimald guest_render_refuses_the_proxy_address_outside_the_lane_set
    - cohort:
      - crates/minimald/src/box_actor/host.rs: `HostMoves` changes the lane set through the helper's new verbs, and `join_quic443_cohort` passes the record's lane bit to the cohort
      test: cargo nextest run -p minimald lane_less_cohort_member_stays_out_of_the_proxy_lane_set
    - kernel:
      - crates/minimald/tests/netns_root_integration.rs: a leg that loads the table rendered with `--proxy-lane` at a namespace address, places two members in their own leaves with only the first in the lane set, and shows the first's connects to the listener port and to 443 accepted and the second's refused with EHOSTUNREACH, both while the cohort blocks UDP 443 and while it does not
      - crates/minvmd/src/net/egress_gate.rs: the interim paragraph of `host_ip_verdict`'s doc comment goes; the gate logic stays as the lane's host half
      test: cargo nextest run -p minimald --run-ignored ignored-only only_the_declaring_cohort_member_reaches_the_proxy_address
  produces:
    - the in-VM refusal of a host-address box with no grant at the proxy's address
  consumes:
    - the cohort's proxy lane at the host gate
  proof: On a Mac, while a GitHub grant box runs with `--network host_ip`, a second host-address box with no grant cannot connect to the proxy's address, and the grant box still reaches the proxy's listener.
  depends on:
    - blocked by #2854

Activity

  1. added
    kind:taskA task the plan skill rendered; the body carries ## Task
    size:L500 to 900 net lines; one PR, and the ceiling
    model:strongestThe strongest model available: unknown ground, or large work that needs care
    on Nov 5, 2026
  2. minimal-foundry commented on Nov 5, 2026

    @minimal-foundry
    Contributor

    Done. #3052 merged.

    branch agent/3047-refuse-a-host-address-box-with-no-grant-the-prox · epic #1501 · PR #3052

    round outcome job
    1 pushed fe547821
    2 pushed 1a994c15

    Updated 2026-11-05T20:44:13.941Z.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind:taskA task the plan skill rendered; the body carries ## Taskmodel:strongestThe strongest model available: unknown ground, or large work that needs caresize:L500 to 900 net lines; one PR, and the ceiling

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      0