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..5f3eab5a --- /dev/null +++ b/04-ISSUES/344-known-gaps-in-the-agents-boundary-accepted-for-now/00-report.md @@ -0,0 +1,107 @@ +--- +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. **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 + 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. 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 + (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. + +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. + *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. + *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 + +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.