carlos / platform Public
| Previous finding | Round 13 assessment | |---|---| | R1-1: flat tenant borrows a nested socket | Fixed by peer-cgroup authentication (§5.4). | | R1-2: aliases and path routes remain public | Fixed by checking the final upstream (§5.1). | | R1-3: new box starts public | Fixed by classification before serving (§5.1). | | R1-4: revoked grants return after restart | Fixed with retained state; fresh-box replay remains an explicit residual (§5.3). | | R1-5: door exceptions fail across routing | Resolved by removing the owner exception and defining the identity transition (§5.4). | | R1-6: socket lifecycle conflicts | Fixed by instance-level ownership (§5.4). | | R1-7: transport and body limits | Resolved at spec level (§5.5). | | R2-1: stamp follows serving | Fixed by the admission barrier (§5.1). | | R2-2: upgrade serves unclassified engines | Fixed by startup classification and refusal of NULL (§5.1). | | R2-3: flat callers borrow door credentials | Fixed by the door’s UID restriction (§§5.4, 6.2). | | R2-4: deployment verification fails | Fixed by watch tickets (§5.8). | | R2-5: port-80 refusal cannot work remotely | Resolved by the narrowed contract (§5.1). | | R3-1: previously admitted requests cross the mark | Fixed for requests admitted to the execution group (§5.1). Finding 2 below concerns a separate, deleted row. | | R3-2: flat tenant injects into a nested caller | Fixed by excluding unisolated execution while armed; historical compromise remains explicitly excluded (§6.2). | | R3-3: grant-only routes lack watch tickets | Fixed: every deploy target receives a ticket (§5.8). | | R4-1: foreign instances and workers remain unisolated | Fixed by arming prerequisites and launch refusals (§6.2). | | R4-2: path routing widens an engine grant | Fixed by exact-host engine dispatch (§5.4). | | R4-3: watch tickets expire mid-watch | Fixed by renewal (§5.8). | | R5-1: minted hostnames cannot classify | Fixed by execution-owner inheritance (§5.1). | | R5-2: arming rejects isolated unit-backed routes | Fixed by distinguishing backing from layout (§6.2). | | R5-3: home edge lacks the probe path | Fixed by signing the probe path (§5.8). | | R6-1: minted row’s own grant is ignored | Fixed by aggregating group grants (§5.1). | | R6-2: static platform domains are refused | Fixed by restricting inheritance to minted instance rows (§5.1). | | R7-1: clearing exposes a still-serving generation | Fixed by stopping the group and proving its cgroups empty (§5.1). | | R7-2: TCP-backed minted rows have no owner | Fixed by explicit ownership and unique non-empty backend matching (§5.1). | | R8-1: upgrade classifies a running declaring build public | Reported case fixed by scanning staged manifests; missing-manifest exposure remains an explicit residual (§5.1). | | R8-2: sleeping unit-backed route cannot clear | Resolved by operator-controlled stop-and-clear (§5.1). | | R9-1: recovery launches declaring GoodVersion after clearing | Fixed by gating the actual selected build (§5.1). | | R10-1: written but unfenced 1 permits recovery launch | Fixed: every declaring launch waits for the current mark’s fence (§5.1). | | R11-1: granted TCP sockets bypass the edge | Fixed by capability exclusion, listener removal and the live-link constraint (§5.1). | | R12-1: application-bound high port remains public | Direct public ingress is excluded by R3’s stated firewall precondition (§5.9). | | R12-2: separate public service row proxies to engine | Existing local rows are refused (§5.9). Cross-box forwarding and requests surviving row removal remain below. |
Reviewed ee51da7f against locally available amadan origin/main at d9149a01. Implementation files match that revision. Static review; no files changed.
1. P1 — Another box can proxy directly to a declaring build over private ingress (§§5.1, 5.9).
Concrete sequence:
- Box A hosts only execution group E. Its firewall admits public traffic only on 80/443, but permits box B to connect privately to port 9000. This satisfies §5.9’s stated public-ingress precondition.
- Box B has an ordinary public
servicerow S targetingA-private-IP:9000. B homes no internal group. - Adopt a build on E that declares
doc_engine, without granting the optionaldoc-enginecapability. The application serves HTTP on port 9000. A’s launch gate confirms dedication, fences E and starts the build. - A public request to S reaches B’s edge, which forwards directly to E’s listener. It never traverses A’s edge.
I1 holds: E starts after its fence completes and remains internal. A is dedicated throughout. Section 5.9’s outside-group refusal applies on A, while S exists on B.
The CLI stores an explicit service address (cli.go:276), and its proxy dials that address directly (edge.go:2405). Crucially, the private-network filter is rendered only when the release declares and holds the capability (render.go:189). Without the grant, the base service allows TCP and denies only metadata addresses (carlos-app@.service:68); the missing grant produces an advisory (caps_pass.go:234). An HTTP endpoint need not use Chromium or JIT to answer.
Suggested fix: Extend the stated, operator-verified ingress precondition to exclude direct backend access from other boxes as well as public addresses. Engine traffic between boxes must enter through the home edge. This preserves R3’s external-firewall approach. Include a remote service row targeting a declaring, ungranted build in the required simulation.
2. P1 — Removing an outside-group proxy row leaves admitted requests outside the launch fence (§§5.1, 5.9).
Concrete sequence:
- E runs a non-declaring build at
127.0.0.1:9000. A separate publicservicerow S targets that address. - A public request resolves S and passes admission. Pause it before upstream dispatch.
- Remove S and let the edge reload. E is now the only proxying group, so §5.9’s dedication check passes.
- Adopt a declaring build on E. Fence E’s group and start the build. The paused request belongs to S’s admission epoch, not E’s group.
- Resume the request. Its retained proxy connects to port 9000 and reaches the declaring build.
I1 holds: E’s fence completes before launch, and its mark never clears. The missing protection concerns a request admitted through a row that no longer exists.
Deletion removes the registry row without draining requests (registry.go:988). Lookup returns an upstream value (edge.go:1202); reload replaces the map (edge.go:993), while an admitted request later invokes its retained proxy (edge.go:1790). Section 5.1 drains the engine group’s requests; §5.9 adds no corresponding fence for removed outside-group rows.
Suggested fix: Make entering dedicated-engine operation fence all previously admitted public proxy requests on the box, including requests retaining deleted or replaced rows. A box-wide admission epoch can use the existing cancellation, completion and timeout rules. Test the sequence above with S’s request held before dispatch.
Overall verdict: reject. Both paths let the public reach a declaring build while I1 holds, without reopening rulings R3 or R4.