diff --git a/docs/security.md b/docs/security.md index 20b1d571..a8b6144b 100644 --- a/docs/security.md +++ b/docs/security.md @@ -52,13 +52,17 @@ shell) on the attacker's behalf. Mitigations are therefore about **bounding capability and inserting human checkpoints**, not about sandboxing the agent from its own tools: -- **Operator-merge convention** — an agent may *push* branches, but the norm - is that **a human (the operator) merges the PR**, keeping a person in the - loop on the highest-value action. This is largely **convention, not a - blanket enforced gate**: the internal forge applies branch protection only on - the `core`-managed config repos (the config-PR merge flow), and it is **not** - set up for external VCS (GitHub etc.) — there, operator-merge is process and - accepted risk, not a technical control. +- **Operator merges, not the agent** — an agent may *push* branches, but a + **human (the operator) merges the PR**, keeping a person in the loop on the + highest-value action. On the **internal forge this is technically enforced, + not just convention**: agents can't create repos (`max_repo_creation = 0`), + so every repo is `core`-created with branch protection **on by default** — + merges restricted to the operators team + a required operators-team approval + (`apply_operator_branch_protection` / the config-repo equivalent) — and an + agent (a write collaborator, not a repo admin) can neither change those + settings nor merge its own PR. It is **not** set up for external VCS (GitHub + etc.), though — there, operator-merge is process + accepted risk, not a + technical control. - **Approvals** — config changes, schedule additions, and other blast-radius-y operations route through the operator approval queue (see [`approvals.md`](approvals.md)).