carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

| Previous finding | Round 3 assessment | |---|---| | R1-1: flat tenant borrows a nested socket | Direct connection blocked by §5.4. The separate process-injection path below remains. | | R1-2: aliases and path routes remain public | Fixed at spec level by the final-route check (§5.1). | | R1-3: new box starts public | Fixed by classification before serving and refusal of NULL (§5.1). | | R1-4: revoked grants return after restart | Fixed for retained local state; fresh-box replay remains explicitly accepted (§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 listener ownership (§5.4). | | R1-7: transport and body limits | Resolved at spec level (§5.5). | | R2-1: stamp follows serving | Partly fixed: reload acknowledgement covers new lookups, but not requests retaining an earlier upstream (§5.1; finding 1 below). | | R2-2: upgrade serves unclassified engines | Fixed by classification before listeners and fail-closed handling (§5.1). | | R2-3: flat callers borrow door credentials | Direct door attack fixed by the UID check (§§5.4, 6.2). The broader identity guarantee still fails through finding 2. | | R2-4: deployment verification fails | Partly fixed: tickets cover declaring releases, but omit routes internal solely through their grant (§5.8; finding 3). | | R2-5: port-80 refusal cannot work remotely | Resolved by the narrowed contract and explicit non-redirecting refusal (§5.1). |

Reviewed 295eb39f against locally available amadan origin/main at f54aa2fc. The implementation files cited below match that revision. No files changed.

  1. P1 — Reload acknowledgement does not fence requests already admitted (§§5.1, 6.3).

A public request resolves a route while its mark is 0 and passes the proposed check. Pause it before upstream dispatch. Adoption writes 1, receives the reload acknowledgement, and starts the declaring release. Resume the request: it still holds the previous upstream and can reach the new engine.

Route lookup returns an upstream value (edge.go:1202); reload replaces the map without invalidating previously selected values (edge.go:993). Requests subsequently dispatch through their retained proxy (edge.go:1775). This can also involve an actual wait: the activator queues requests behind a stopping instance, wakes it again, and then invokes the supplied proxy (activator.go:1554, activator.go:5404).

Suggested fix: Make the acknowledgement cover a per-route admission fence and the draining or cancellation of previously admitted public requests before activation. Queued requests must not cross the release switch using their previous admission. A second unsynchronised check merely moves the race.

  1. P1 — A flat tenant can inject code into a granted nested caller (§§5.4, 6.1–6.2).

Put ungranted flat app A beside granted nested app B, whose executable is dynamically linked. A writes a library into B’s data directory and adds LD_PRELOAD pointing to it in B’s instance environment file. When B next starts, the library executes inside B’s legitimate slice and connects to B’s engine socket. The cgroup check authenticates B, and both grant checks pass. Neither the direct-socket refusal nor the door UID check intervenes.

The existing layout code explicitly identifies flat tenants’ same-UID write access to sibling directories (preflight.go:181). Nested launches read their instance environment files (backend_exec.go:2701); childEnv passes their supplied variables through (backend_exec.go:2817). The trampoline validates environment syntax and executes with that environment (exec.go:116). The nested unit binds B’s data directory and runs in B’s slice (carlos-instance@.service:33, carlos-instance@.service:53).

Suggested fix: Enforce a box-wide prerequisite excluding untrusted flat processes before enabling engine caller identities, including later flat launches and reversions. Alternatively, isolate callers’ writable state from flat tenants. Filtering one loader variable would not establish that isolation.

  1. P2 — Grant-only internal routes still cannot complete URL-based deployment verification (§§5.1, 5.8).

Give a route the doc-engine grant while its release does not declare doc_engine. Deploy another non-declaring release. Section 5.1 keeps the route internal because the grant remains, but §5.8 issues watch tickets only for declaring releases. The ordinary watch therefore receives the internal refusal even when the deployment is healthy.

Capability grants are stored independently of release versions (registry.go:1613). URL verification sends an ordinary GET (deploy.go:1546) and requires a successful response (deploy.go:1563).

Suggested fix: Make watch-ticket availability cover every authorised deployment target that can be internal, including grant-only routes. Since classification is box-local, issuing narrowly scoped tickets for all authorised deploy targets avoids requiring the console to infer that classification.

Overall verdict: reject. The remaining public-admission race and mixed-layout identity attack violate the stated anti-goals.