From d7999e6fc99888eb03c83eed24ea6003ec5da99b Mon Sep 17 00:00:00 2001 From: jochen Date: Fri, 9 Oct 2026 11:49:25 +0200 Subject: [PATCH] ADR 0266: the setuid search's bound is 15 minutes, and the two routes and the restart condition the review of 2026-10-09 found Item 10 said two minutes; the engine's bound is 15, with a two-minute limit inside it still to settle. What still remains now names a build from another repository registering a module (mesh-controller 174), the forge's tools changing its protection (mesh-catalog 153), and the urgent condition every engine restart raises (mesh-controller 175). --- ...hat-cannot-become-root-without-a-person.md | 37 ++++++++++++++++++- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/02-DECISIONS/0266-on-the-control-node-agents-run-under-an-account-of-their-own-that-cannot-become-root-without-a-person.md b/02-DECISIONS/0266-on-the-control-node-agents-run-under-an-account-of-their-own-that-cannot-become-root-without-a-person.md index a357c17c..3d380c70 100644 --- a/02-DECISIONS/0266-on-the-control-node-agents-run-under-an-account-of-their-own-that-cannot-become-root-without-a-person.md +++ b/02-DECISIONS/0266-on-the-control-node-agents-run-under-an-account-of-their-own-that-cannot-become-root-without-a-person.md @@ -153,8 +153,13 @@ the C locale. It finds a way to root when the account: tool runner's credential is one of those; 10. could run a program no installed package owns that is setuid with owner root, or setgid with group root whoever owns it, on any local filesystem mounted without `nosuid` (container and image layers, network - and pseudo filesystems excepted). The engine searches for these at most hourly and gives the search two - minutes; + and pseudo filesystems excepted). The engine searches for these in the background, at most hourly, and + lets one search run for at most 15 minutes. Until the first search after the engine starts has finished, + the verdict is *not judged yet*. *Corrected 2026-10-09: this said the search gets two minutes; the engine's + bound on a search is 15 minutes (mesh-host pull request 61). Its `find` and the package queries still carry + a two-minute limit of their own inside that bound, so as written a search longer than two minutes ends + incomplete before the 15 minutes are reached; which of the two limits holds is for that pull request to + settle;* 11. lives on a machine whose kernel leaves hard or symbolic links to other accounts' files unprotected (`fs.protected_hardlinks` or `fs.protected_symlinks` is 0). @@ -313,6 +318,34 @@ found around it and are closed on the mesh's main line: - **The tool runner on the control node is still the operator account** (Considered Options), so a tool found tomorrow that reads, writes or runs a caller's path or command is a way round this record until it is bounded. Each is a defect of that tool, found by review. +- **A build from another repository registered a module** (found in review, 2026-10-09). The controller's + `build` verb cloned any repository as given, and the outcome registered the module its `module.json` named, + from that repository: a module is registered by name and its source overwritten, and "only a commit on the + trunk is published" (ADR 0238) checked the trunk of the repository built. An agent that made a repository, + or forked the catalogue or the node-engine, and committed a `sudo` module granting itself a rule without a + password, had the next push make it root on every node. `rebuild`, `replay --register` and `assign` with + `build` reached the same take-in. Closed by mesh-controller pull request 174, once merged after pull request + 164: an outcome registers a module only from the repository the catalogue already builds it from, a new + module only from a repository the catalogue already builds another from (a merge adding one), and anything + else only when the build was asked at the controller's terminal; through a verb, a build of a repository + the catalogue builds nothing from is not asked at all, and a failed gate puts back only a build of the + module's own repository. +- **The forge's tools could change the forge's protection** (found in review, 2026-10-09). `gitea_api` sent + any call with a token minted for the forge's administrator, `write:admin` included: an agent could drop a + branch's protection or its required checks, set the merge check's status, write to the default branch, + delete and recreate a repository the mesh builds from, or merge its own pull request past the checks; and + `gitea_branch_protection_set` could weaken a rule. Closed by mesh-catalog pull request 153: `gitea_api` + reads anything but the forge's administration and writes only what an author writes, protection is only + made stronger, a merge needs every required status a success and merges only the head that was checked, a + guarded repository is not deleted, and the token is minted without `write:admin`. A merge after the + operator's yes, of a pull request whose checks passed, works as before. The token still belongs to the + forge's administrator; a non-admin account for the tools is a follow-up. +- **Every node-engine restart raises `agent-can-become-root`.** Until the engine's first search for setuid + programs finishes (§3 item 10), the verdict is *not judged yet*, and the self-check (§4) raises the urgent + condition on every restart. Proposed in mesh-controller pull request 175: while that first search is within + its bound (15 minutes, and one statement more), the condition is not raised; the account is still not + confined, `node show` still says not judged, and the condition is raised as before once the search fails, + runs out its bound or finds a way to root. - **The self-check judges this record's account only.** ADR 0259's own root probe (mesh-controller pull request 154) asks the same question through the `sudo` module; it must call this record's judgement, one function, rather than keep a second answer.