ci(risk): pane host ops and allowlists are high risk

Merged
TE
15d ago
+63-0

Summary

The risk-tier classifier now grades high the files that decide what an agent pane's web page may make the host do or read. Before this, they all graded normal.

#22646 added the page op chat.asks.pending to AgentPageOps. Its handler, AgentPanePendingAsks.swift, opens its own connection to the local acpmux daemon and reads another chat's permission asks. Until review caught it, the read reached a peer daemon. The fix named the chat local/<id> and refused replies that name a peer. The whole change graded normal by path, so the next such op would have been caught only by a reviewer's judgment, not by the path tiers.

New rule in scripts/ci/risk_tier.py, "agent pane host op or allowlist", placed right after the socket and relay rule:

  • CmuxNextAgentPane/AgentPageProvider.swift: the AgentPageOps list and its call dispatch. Every new op edits this list.
  • CmuxNextAgentPane/AcpmuxPaneMethods*.swift: the _acpmux/* methods a pane may relay and their knownParams.
  • CmuxNextAgentPane/AgentPaneEnvironmentRequest.swift, AgentPaneReplyRequest.swift: the page-op param tables.
  • CmuxNextAgentPane/AgentPaneTransport+Check.swift: the frame check.
  • CmuxNextAgentPane/AcpmuxPathPolicy.swift: the folder policy.
  • CmuxNextAgentPane/AgentPanePendingAsks.swift: a host op that opens its own daemon connection for a page.
  • CmuxNextAgentPane/AgentPaneTransport+Frames.swift: decide(), the gesture rule that spends a click's ticket (and grants folder roots).
  • CmuxNextAgentPane/AgentPaneGestureIntent.swift: which methods a click's ticket may redeem.
  • CmuxNextAgentPane/AgentPaneUserGestures.swift: the click tickets themselves (reserve, consume, redeem).
  • CmuxNextAgentPane/AgentPaneModel+Actions.swift: connectActions, the app actions a page may run through action.run.
  • CmuxNextAgentPane/AgentPaneTransport+RelayedAllow.swift: the decision proof a relayed allow carries, signed with the person key.
  • CmuxNextAgentPane/AgentPaneTransport+PickedFolder.swift: a folder the person picks becomes a root the page's requests pass.
  • CmuxNextAgentPane/AgentPaneTransport+FullAccess.swift: the refusal of a switch into a mode that skips approvals.
  • cmux-tui/crates/cmux-agent-pane-policy/*: the Rust mirror (policy.json, src and Cargo.toml).
  • cmux-tui/crates/acpmux/src/server/remote_guard*: what acpmux allows from a non-local connection.

The rest of CmuxNextAgentPane stays normal (for example AgentPaneView.swift, AgentPageProvider+Scroll.swift, AgentPaneTransportPacer.swift). The policy tests stay low, because the test rule comes first. docs/ci/risk-tiers.md gets a new row under the socket and relay access policy kind, with #22646 as its evidence. There are still six kinds.

This touches risk_tier.py, so this PR is risk:high and needs a person's approval.

Review follow-up (c0695a250b0b)

The independent review of c0b5b4ed passed and named three gatekeepers outside the rule; they are added above, with test cases. Checked with risk_tier.py's classify_path on this head: all three grade high, and AgentPaneView.swift, AgentPaneModel+Composer.swift and AgentPaneTransportPacer.swift stay normal. git merge-tree with #23371 at 0b7d7fed still merges cleanly. Lines touched at f08aa0f3446e: risk_tier.py new 95-111, tests/test_risk_tier.py new 201-238, docs/ci/risk-tiers.md line 30 (all new lines). A second review (of c0695a25) passed and named AgentPaneUserGestures.swift, added in f08aa0f3. The test file was not run on this Mac (a hook refuses it); CI's risk tier tests job runs it.

Base merge and review follow-up (05ee5b880ba7)

Merged feat-cmux-next afaf26df (13fdb5f9; base hadn't touched risk_tier.py). The independent review of 13fdb5f9 passed (SHIP) and named three transport files that also decide what a page may make the host do: +RelayedAllow, +PickedFolder, +FullAccess. Added in 945913d5 (test) and 05ee5b88 (rule and docs row). python3 -I tests/test_risk_tier.py ran on this Mac this time: red at 945913d5 ('normal' != 'high' for exactly those three paths), green at 05ee5b88 (31 tests OK).

Changelog

none

Testing

New tests: test_agent_pane_host_ops_and_allowlists_are_high and test_ordinary_agent_pane_ui_and_policy_tests_stay_below_high in tests/test_risk_tier.py. The risk tier tests workflow runs them on this PR (python3 tests/test_risk_tier.py -v).

Observed / Not run

Observed:

  • A hook on this Mac refuses python3 tests/test_risk_tier.py (heavy work on an interactive Mac). So I got red and green from the same classify function the tests call, one path at a time: risk_tier.py classify --files <one path> --json.
    • On base (red): every new path returned normal (AgentPageProvider.swift, AcpmuxPaneMethods.swift, AcpmuxPaneMethods+Params.swift, AgentPaneEnvironmentRequest.swift, AgentPaneReplyRequest.swift, AgentPaneTransport+Check.swift, AcpmuxPathPolicy.swift, AgentPanePendingAsks.swift, policy.json, params.rs, remote_guard.rs).
    • On head (green): each of those returned high. AgentPaneView.swift, AgentPageProvider+Scroll.swift and AgentPaneTransportPacer.swift returned normal. cmux-agent-pane-policy/tests/swift.rs and acpmux/tests/remote_guard.rs returned low.
  • python3 scripts/cmux-next/prepush-gate.py: no new violations.
  • python3 scripts/verify-local.py: 10 of 11 checks passed. localization failed on parity in catalogs this PR doesn't touch (base debt).
  • git merge-tree --write-tree against #23371's head (0b7d7fed) merges cleanly. The two PRs change different lines of the same three files.

Not run before 05ee5b88: the full tests/test_risk_tier.py suite locally (the hook refused it then). At 05ee5b88 it ran locally: 31 tests OK (see the follow-up section above).

Agent session: cosmic-gray

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

The risk-tier classifier now grades high the files that decide what an agent pane's web page may make the host do or read, so a security slip like #22646's chat.asks.pending (which reached a peer daemon until review caught it) gets caught by path instead of by reviewer judgment.

  • Adds a high-risk rule in scripts/ci/risk_tier.py covering the page ops list, the relayable _acpmux methods and params, the page-op param tables, the frame check, the gesture rule (the click-minted tickets and decide spending one), the app actions a page may run, the folder policy and the picked-folder roots, the relayed-allow proof, the full-access refusal, the Rust mirror, and acpmux's remote guard.
  • Ordinary pane UI files stay normal and the policy tests stay low.
  • Adds matching tests and a docs row; this PR touches risk_tier.py itself, so it grades high and needs a person's approval.