From 7d4678c5fb2861b22079784bdd7412639787d92f Mon Sep 17 00:00:00 2001 From: jochen Date: Fri, 9 Oct 2026 12:03:36 +0200 Subject: [PATCH 1/6] Issue 344: record the known gaps in the agent's boundary, accepted for now by the operator --- .../00-report.md | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 04-ISSUES/344-known-gaps-in-the-agents-boundary-accepted-for-now/00-report.md diff --git a/04-ISSUES/344-known-gaps-in-the-agents-boundary-accepted-for-now/00-report.md b/04-ISSUES/344-known-gaps-in-the-agents-boundary-accepted-for-now/00-report.md new file mode 100644 index 00000000..bd5cec58 --- /dev/null +++ b/04-ISSUES/344-known-gaps-in-the-agents-boundary-accepted-for-now/00-report.md @@ -0,0 +1,73 @@ +--- +status: open +opened: 2026-10-09 +located-in: [] +fixed-by: +amended-design: +--- + +# 344. Known gaps in the agent's boundary, accepted for now + +## Symptom + +Three reviews on 2026-10-09 checked whether an agent can become root or approve in the operator's name. They +covered ADR 0266 (agents on the control-node run under an account of their own), the root routes found beside it, +and ADR 0259 (the operator's answers on any channel). Most findings are being fixed in the pull requests those +records name. The gaps below are **not** being fixed now. + +The operator decided on 2026-10-09: *"that's not too big of an issue, i kind of trust you to not do weird stuff all +of a sudden. We can improve security later on, you should note down the known gaps though."* This issue is that +note. Each gap says what is open, why it matters, and what would close it. + +## The gaps + +1. **On every machine but the control-node, agents run as the operator, with passwordless sudo.** ADR 0266 gives + agents an account of their own on the control-node only. On the laptop, the workstation and the home server, an + agent session holds everything the operator's account holds, root included. + *Closes with:* a follow-up decision that extends ADR 0266 to every node where agents run. + +2. **Tools that run a caller's command as the operator remain on those machines.** These are the login shell's + `execute` (withheld on the control-node by [ADR 0268](../../02-DECISIONS/0268-the-login-shells-execute-is-withheld-on-the-control-node-until-a-call-to-it-needs-a-persons-approval.md)), + the launcher's `run` and the terminal emulator's `open`. Through any of them, an agent reaches root on that + machine. + *Closes with:* `execute: withhold` mesh-wide once the operator's command exists (issue 343), and the + approval mark of [research 039](../../01-RESEARCH/039-a-tool-that-needs-a-persons-approval/00-overview.md) + for the other two. + +3. **The operator's chat client runs on a machine where agents run as the operator.** An agent there can focus the + desktop client and tap Approve. Telegram then authenticates the tap as the operator, and the router issues a + genuine warrant. The client's data directory was also found readable by every account (directories 755, files + 644), so another account could copy the logged-in session. + *Closes with:* gap 1 on that machine; no agent access to the operator's display; the client's data kept 0700. + +4. **One X display gives its clients no isolation.** Any program with access to the operator's display can read + other windows and send them input. + *Closes with:* agents' accounts get no access to the operator's display (no X authority cookie). + +5. **The acts a warrant authorises can still be called directly, as verbs.** Release, stop, a plan's go and stop, a + service restart and silencing a condition all remain open to any agent through a tool runner. So "the mesh does + this only on approval" does not hold yet. + *Closes with:* the approval mark of research 039, which withholds those verbs from agents. + +6. **The tool runner on the control-node runs as the operator** and can read the forge administrator's password + file. A future tool that reads a path the caller chooses could leak it. + *Closes with:* the tool runner under an account of its own; secrets read only by the module that owns them. + +7. **The forge's tools still use a site administrator's token.** The tools' own guards refuse admin and + protection-weakening calls. The account itself could do more, because the forge puts protection edits under the + repository scope. + *Closes with:* a non-administrator forge account for the tools, with write access through a team. + +8. **The controller's credential can rewrite the router's record** (identities, asks, the hour after a link). The + router itself enforces the hour, but its record is only as safe as the controller. + *Closes with:* the router's state in a bucket only the router may write. + +9. **The root search's two bounds disagree.** The node-engine's search for programs that run as root stops itself + after two minutes, while the record allows it fifteen. On a large disk the verdict stays "not judged". + *Closes with:* one bound, settled in the node-engine with ADR 0266. + +## Why it is an issue + +Each gap is a known way around a rule the mesh states. A gap that is written down can be weighed and closed. A +gap that is forgotten turns into a belief that the rule holds. This issue stays open until every gap above is +closed or decided against in writing. From e8f0f43f1b50af736f2711770ebb7222e9d34a12 Mon Sep 17 00:00:00 2001 From: jochen Date: Fri, 9 Oct 2026 12:09:17 +0200 Subject: [PATCH 2/6] Issue 344: an agent can merge its own pull request --- .../00-report.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/04-ISSUES/344-known-gaps-in-the-agents-boundary-accepted-for-now/00-report.md b/04-ISSUES/344-known-gaps-in-the-agents-boundary-accepted-for-now/00-report.md index bd5cec58..506d55eb 100644 --- a/04-ISSUES/344-known-gaps-in-the-agents-boundary-accepted-for-now/00-report.md +++ b/04-ISSUES/344-known-gaps-in-the-agents-boundary-accepted-for-now/00-report.md @@ -66,6 +66,14 @@ note. Each gap says what is open, why it matters, and what would close it. after two minutes, while the record allows it fifteen. On a large disk the verdict stays "not judged". *Closes with:* one bound, settled in the node-engine with ADR 0266. +10. **An agent can merge its own pull request.** No mesh repository's main requires an approval on the forge + (`required_approvals: 0`), and the forge tool merges as the forge's administrator once the required checks are + green. An agent can therefore change a module that runs on every node, open the pull request, wait for the + checks and merge it, and the controller walks the change out. The checks judge whether every machine still + composes, not what the change is for. The operator's yes in a session is a convention, and nothing checks it. + *Closes with:* a merge that needs the operator's own approval: a required approval on the forge from the + operator's personal account only, or an approval through ADR 0259's asks. + ## Why it is an issue Each gap is a known way around a rule the mesh states. A gap that is written down can be weighed and closed. A From 11d261e582891a9bd0c153ec10df919a5c5af40e Mon Sep 17 00:00:00 2001 From: jochen Date: Fri, 9 Oct 2026 12:19:54 +0200 Subject: [PATCH 3/6] Issue 344: the screen is readable through the display server's tools --- .../00-report.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/04-ISSUES/344-known-gaps-in-the-agents-boundary-accepted-for-now/00-report.md b/04-ISSUES/344-known-gaps-in-the-agents-boundary-accepted-for-now/00-report.md index 506d55eb..b40243f2 100644 --- a/04-ISSUES/344-known-gaps-in-the-agents-boundary-accepted-for-now/00-report.md +++ b/04-ISSUES/344-known-gaps-in-the-agents-boundary-accepted-for-now/00-report.md @@ -74,6 +74,12 @@ note. Each gap says what is open, why it matters, and what would close it. *Closes with:* a merge that needs the operator's own approval: a required approval on the forge from the operator's personal account only, or an approval through ADR 0259's asks. +11. **Any caller of the mesh's tools can see the operator's screen.** The display server module's tools answer every + window's title, which can hold a mail subject or a chat's name, and can return a screenshot as data over the bus + (mesh-catalog #154). A session on another machine needs no access to the display to read it. + *Closes with:* the approval mark of research 039 for screenshot and window-listing tools, or limiting them to + the operator's own sessions. + ## Why it is an issue Each gap is a known way around a rule the mesh states. A gap that is written down can be weighed and closed. A From 3143f5c698c9a1d2cbee8903dab5632e5bc60d24 Mon Sep 17 00:00:00 2001 From: jochen Date: Fri, 9 Oct 2026 12:56:41 +0200 Subject: [PATCH 4/6] Issue 344: gap 9 narrowed by mesh-host #61; the tools' sudo and the forge's rule precedence --- .../00-report.md | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/04-ISSUES/344-known-gaps-in-the-agents-boundary-accepted-for-now/00-report.md b/04-ISSUES/344-known-gaps-in-the-agents-boundary-accepted-for-now/00-report.md index b40243f2..6c921f8d 100644 --- a/04-ISSUES/344-known-gaps-in-the-agents-boundary-accepted-for-now/00-report.md +++ b/04-ISSUES/344-known-gaps-in-the-agents-boundary-accepted-for-now/00-report.md @@ -62,9 +62,11 @@ note. Each gap says what is open, why it matters, and what would close it. router itself enforces the hour, but its record is only as safe as the controller. *Closes with:* the router's state in a bucket only the router may write. -9. **The root search's two bounds disagree.** The node-engine's search for programs that run as root stops itself - after two minutes, while the record allows it fifteen. On a large disk the verdict stays "not judged". - *Closes with:* one bound, settled in the node-engine with ADR 0266. +9. **On a large data pool the root search may never finish.** The node-engine's search for programs that run as + root now has one bound of fifteen minutes (mesh-host #61; the inner two-minute limit is gone). On a machine with + a very large data pool the walk can still run past it, and the verdict then stays "not judged". That is loud, + not silent. + *Closes with:* setuid turned off on the data datasets, so the walk skips them. 10. **An agent can merge its own pull request.** No mesh repository's main requires an approval on the forge (`required_approvals: 0`), and the forge tool merges as the forge's administrator once the required checks are @@ -72,7 +74,8 @@ note. Each gap says what is open, why it matters, and what would close it. checks and merge it, and the controller walks the change out. The checks judge whether every machine still composes, not what the change is for. The operator's yes in a session is a convention, and nothing checks it. *Closes with:* a merge that needs the operator's own approval: a required approval on the forge from the - operator's personal account only, or an approval through ADR 0259's asks. + operator's personal account only, or an approval through ADR 0259's asks. That holds only when the forge's + tools cannot act as another user (gap 12) and cannot post an approving review themselves. 11. **Any caller of the mesh's tools can see the operator's screen.** The display server module's tools answer every window's title, which can hold a mail subject or a chat's name, and can return a screenshot as data over the bus @@ -80,6 +83,21 @@ note. Each gap says what is open, why it matters, and what would close it. *Closes with:* the approval mark of research 039 for screenshot and window-listing tools, or limiting them to the operator's own sessions. +12. **The forge's tools can act as any forge user.** The tools' token belongs to a site administrator, and the + forge lets an administrator act as another user by adding `sudo=` to a call. The generic API tool passed + that query on unchanged. Measured on 2026-10-09: a read through the tool with `sudo` set to the operator's + account answered as the operator. An agent could therefore post comments, pull requests and approving reviews + as the operator. The operator's own forge account is also a site administrator, so acting as it is acting as + an administrator. + *Closes with:* the tool sending only a known list of query keys and never `sudo` (being fixed in + mesh-catalog #153); later, a non-administrator account for the tools (gap 7). + +13. **The forge applies only the first protection rule that matches a branch.** A rule named for the branch comes + before a glob rule. A weak rule named for a branch next to a strong glob would leave the branch weakly protected, + while a reader that asks "does any rule protect it" sees it as protected. No repository has such a pair today + (every rule is named `main`), and the tools refuse to create one. + *Closes with:* every reader judging the first matching rule, as the forge does. + ## Why it is an issue Each gap is a known way around a rule the mesh states. A gap that is written down can be weighed and closed. A From d7c97d02fa17483ce238fd14131059ab352e4192 Mon Sep 17 00:00:00 2001 From: jochen Date: Fri, 9 Oct 2026 12:56:54 +0200 Subject: [PATCH 5/6] Issue 344: name the node-engine's repository as code --- .../00-report.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/04-ISSUES/344-known-gaps-in-the-agents-boundary-accepted-for-now/00-report.md b/04-ISSUES/344-known-gaps-in-the-agents-boundary-accepted-for-now/00-report.md index 6c921f8d..66cecfd6 100644 --- a/04-ISSUES/344-known-gaps-in-the-agents-boundary-accepted-for-now/00-report.md +++ b/04-ISSUES/344-known-gaps-in-the-agents-boundary-accepted-for-now/00-report.md @@ -63,7 +63,7 @@ note. Each gap says what is open, why it matters, and what would close it. *Closes with:* the router's state in a bucket only the router may write. 9. **On a large data pool the root search may never finish.** The node-engine's search for programs that run as - root now has one bound of fifteen minutes (mesh-host #61; the inner two-minute limit is gone). On a machine with + root now has one bound of fifteen minutes (`mesh-host` #61; the inner two-minute limit is gone). On a machine with a very large data pool the walk can still run past it, and the verdict then stays "not judged". That is loud, not silent. *Closes with:* setuid turned off on the data datasets, so the walk skips them. From 57cfdb5cf9ddac61ad405418c738f339fa122d1c Mon Sep 17 00:00:00 2001 From: jochen Date: Fri, 9 Oct 2026 13:49:54 +0200 Subject: [PATCH 6/6] Issue 344: gaps 12 and 13 closed by mesh-catalog #153 and mesh-controller #177 --- .../00-report.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/04-ISSUES/344-known-gaps-in-the-agents-boundary-accepted-for-now/00-report.md b/04-ISSUES/344-known-gaps-in-the-agents-boundary-accepted-for-now/00-report.md index 66cecfd6..5f3eab5a 100644 --- a/04-ISSUES/344-known-gaps-in-the-agents-boundary-accepted-for-now/00-report.md +++ b/04-ISSUES/344-known-gaps-in-the-agents-boundary-accepted-for-now/00-report.md @@ -89,14 +89,16 @@ note. Each gap says what is open, why it matters, and what would close it. account answered as the operator. An agent could therefore post comments, pull requests and approving reviews as the operator. The operator's own forge account is also a site administrator, so acting as it is acting as an administrator. - *Closes with:* the tool sending only a known list of query keys and never `sudo` (being fixed in - mesh-catalog #153); later, a non-administrator account for the tools (gap 7). + *Closed* on 2026-10-09 by mesh-catalog #153: the tools send only a known list of query keys, never `sudo`, and + every caller-supplied path segment is checked, so `..` cannot reach another endpoint. A non-administrator account + for the tools (gap 7) remains. 13. **The forge applies only the first protection rule that matches a branch.** A rule named for the branch comes before a glob rule. A weak rule named for a branch next to a strong glob would leave the branch weakly protected, while a reader that asks "does any rule protect it" sees it as protected. No repository has such a pair today (every rule is named `main`), and the tools refuse to create one. - *Closes with:* every reader judging the first matching rule, as the forge does. + *Closed* on 2026-10-09 by mesh-controller #177: the build-source check judges the first matching rule, as the + forge does. ## Why it is an issue