Summary
On the walled single-database hosted-SaaS shape (OS_TENANCY_POSTURE=isolated, HotCRM as composed artifact, OS_AI_STUDIO_AGENTS=ask), the automation-domain write routes are not gated by manage_metadata. A plain tenant org owner — holding organization_admin only, demonstrably without manage_metadata / studio.access — can create, modify and delete automation flows. Flow metadata is environment-scoped, not organization-scoped, so one tenant's write lands on the layer every organization runs on: a flow one tenant deletes vanishes for all tenants and the platform admin; a flow one tenant creates appears for all of them.
This satisfies both of the deployment's highest-severity criteria at once: metadata is mutable by a tenant, and the mutation crosses the tenant wall.
Measured over HTTP (fresh composed boot, framework 8798cd2, hotcrm 3940736)
Same northwind session (org owner, no manage_metadata) — the control that proves the account is unprivileged:
PUT /api/v1/meta/:type/:name, POST /api/v1/ai/tools/:tool/execute, POST /api/v1/packages/* → all 403.
Yet on the automation domain:
POST /api/v1/automation {name:'probe_flow_x',label:'Probe Flow X',type:'autolaunched',nodes:[],edges:[]}
→ 200 {success:true, data:{name:'probe_flow_x',…}} # created
PUT /api/v1/automation/probe_flow_x {…}
→ 200 {success:true} # modified
DELETE /api/v1/automation/lead_auto_assignment
→ 200 {success:true, data:{name:'lead_auto_assignment', deleted:true}} # deleted a HotCRM-shipped flow
Cross-tenant blast radius, verified by reading back as three different principals:
| flow | northwind (actor) | contoso (unrelated tenant) | founder (platform admin) |
|---|
lead_auto_assignment (deleted) | 404 | 404 | 404 |
probe_flow_x (injected) | 200 | 200 | 200 |
So one tenant deleted a flow out from under every other tenant, and injected a flow into the shared layer that every tenant now sees.
Root cause
The /api/v1/automation POST/PUT/DELETE handlers register without the manage_metadata authorization the parallel /api/v1/meta/* writes carry (route ledger: packages/runtime/src/route-ledger.ts:317,329,330; the /meta/* gate is manage_metadata per packages/rest/src/rest-server.ts). A flow is authored metadata registered at environment scope, so an ungated write is both a privilege escalation and a cross-tenant one on any multi-organization deployment.
Requested fix
Gate the automation-domain write routes with manage_metadata, identical to /api/v1/meta/*. On a walled posture, environment-scoped metadata writes must be refused for principals without manage_metadata — the same rule that already makes /meta/*, /packages/* and the AI authoring tools 403 for a tenant on this shape.
Found during a hosted-SaaS lockdown test pass. Same batch as #10131 and #10132 (walled-shape org-attribution / catalog-visibility defects).
Summary
On the walled single-database hosted-SaaS shape (
OS_TENANCY_POSTURE=isolated, HotCRM as composed artifact,OS_AI_STUDIO_AGENTS=ask), the automation-domain write routes are not gated bymanage_metadata. A plain tenant org owner — holdingorganization_adminonly, demonstrably withoutmanage_metadata/studio.access— can create, modify and delete automation flows. Flow metadata is environment-scoped, not organization-scoped, so one tenant's write lands on the layer every organization runs on: a flow one tenant deletes vanishes for all tenants and the platform admin; a flow one tenant creates appears for all of them.This satisfies both of the deployment's highest-severity criteria at once: metadata is mutable by a tenant, and the mutation crosses the tenant wall.
Measured over HTTP (fresh composed boot, framework
8798cd2, hotcrm3940736)Same
northwindsession (org owner, nomanage_metadata) — the control that proves the account is unprivileged:PUT /api/v1/meta/:type/:name,POST /api/v1/ai/tools/:tool/execute,POST /api/v1/packages/*→ all 403.Yet on the automation domain:
Cross-tenant blast radius, verified by reading back as three different principals:
lead_auto_assignment(deleted)probe_flow_x(injected)So one tenant deleted a flow out from under every other tenant, and injected a flow into the shared layer that every tenant now sees.
Root cause
The
/api/v1/automationPOST/PUT/DELETE handlers register without themanage_metadataauthorization the parallel/api/v1/meta/*writes carry (route ledger:packages/runtime/src/route-ledger.ts:317,329,330; the/meta/*gate ismanage_metadataperpackages/rest/src/rest-server.ts). A flow is authored metadata registered at environment scope, so an ungated write is both a privilege escalation and a cross-tenant one on any multi-organization deployment.Requested fix
Gate the automation-domain write routes with
manage_metadata, identical to/api/v1/meta/*. On a walled posture, environment-scoped metadata writes must be refused for principals withoutmanage_metadata— the same rule that already makes/meta/*,/packages/*and the AI authoring tools 403 for a tenant on this shape.Found during a hosted-SaaS lockdown test pass. Same batch as #10131 and #10132 (walled-shape org-attribution / catalog-visibility defects).