From 7e86430913da93473780a2d027ef706439814306 Mon Sep 17 00:00:00 2001 From: tegwick Date: Mon, 5 Oct 2026 16:23:05 +0200 Subject: [PATCH] MASON-IN-0004: record the policy-plus-AppRole escalation path in ops-mason-build Finding from the inbound-library lane (ILIB-WP-0003): the build grant can write a policy, bind it to an AppRole and mint a secret-id, yielding a token outside its own denies. Options recorded for founder decision; the policy is unchanged. Co-Authored-By: Claude Opus 5.5 Assistant: claude-code Assistant-Model: opus Assistant-Process: 1170398@bnt-lap001 Assistant-Session: 622cd705-cb31-4322-ba08-dd42e44fa583 --- intakes/intakes.md | 57 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/intakes/intakes.md b/intakes/intakes.md index 6fa5ed4..56c9178 100644 --- a/intakes/intakes.md +++ b/intakes/intakes.md @@ -71,3 +71,60 @@ notes: >- fulfilled; the accepted conformance gaps and their 2026-12-21 review remain declared and are not marked conformant by this intake closure. ``` + +## MASON-IN-0004 — Close the policy-plus-AppRole escalation path in ops-mason-build + +```yaml +id: MASON-IN-0004 +kind: intake +title: Close the policy-plus-AppRole escalation path in ops-mason-build +status: open +origin: review +origin_ref: inbound-library ILIB-WP-0003 (finding raised 2026-10-05 while preparing the first grant) +priority: high +owner: ops-mason +requested_by: founder +description: >- + policies/ops-mason-build.hcl says OpenBao, not convention, enforces "ops-mason + never reads a secret value". The explicit denies on platform/, operators/ and + secret/ data hold only for tokens that carry ops-mason-build. The same grant can + also do the following: + (1) create or update any ACL policy except its own (sys/policies/acl/*); + (2) create or update any AppRole role and read or write anything beneath it + (auth/approle/role/*), which includes reading role-id and minting secret-id; + (3) do the same for Kubernetes auth roles. + A grant holder could therefore write a policy granting read on platform/data/*, + bind it to a new AppRole, read that role's role-id, mint a secret-id and log in. + The resulting token does not carry ops-mason-build, so none of its denies + apply. Kubernetes roles allow the same path for anyone holding a + service-account JWT. This was confirmed by reading the policy text. It was + not exercised. + The builder legitimately needs to write policies and mint secret-ids to deliver + AppRole lanes, as it did for inbound-library-imap-approle on 2026-10-05. A + path-level deny on secret-id would therefore break every build. Parameter + constraints such as allowed_parameters with token_policies=workload-kv-read-* + narrow the role binding but not policy content, because a policy with a + conforming name can still grant platform/data/*. +options: >- + (a) Separation of duties: ops-mason drafts policy HCL in the plan, and the + founder applies the policy write in an attended operator session. The grant + loses sys/policies/acl/* create/update and keeps role binding and delivery, + restricted by allowed_parameters to the policy names the plan approved. + (b) Detective control: after every build, re-read the written policy and role + and compare them to the approved build_spec (policy text derived from kv_path + and capabilities). Alert from the OpenBao audit log on any sys/policies/acl + write or role secret-id mint by a claude-* display_name that has no matching + build-log record. + (c) Two grants: a read-only survey grant (survey, metadata, capabilities), and + a build grant minted only after plan approval and scoped by allowed_parameters + to that plan's exact policy and role names. Bao policies cannot template on + plan content, so this means minting a per-plan policy at grant time, itself an + operator act. + These can be combined, for example (b) now and (a) or (c) as the structural fix. + This is a decision for the founder. Do not widen or loosen ops-mason-build + while it is open. +notes: >- + A survey needs only (c)'s read-only grant. Today MASON-WP-0008 plan-survey runs + under the full build grant, so separating them also reduces what a survey + session can do. +```