fix(gateway): propagate real gateway client into plugin subagent runtime

Plugin subagent dispatch used a hardcoded synthetic client carrying
operator.admin, operator.approvals, and operator.pairing for all
runtime.subagent.* calls. Plugin HTTP routes with auth:"plugin" require
no gateway auth by design, so an unauthenticated external request could
drive admin-only gateway methods (sessions.delete, agent.run) through
the subagent runtime.

Propagate the real gateway client into the plugin runtime request scope
when one is available. Plugin HTTP routes now run inside a scoped
runtime client: auth:"plugin" routes receive a non-admin synthetic
operator.write client; gateway-authenticated routes retain admin-capable
scopes. The security boundary is enforced at the HTTP handler level.

Fixes GHSA-xw77-45gv-p728
This commit is contained in:
Robin Waslander
2026-03-11 03:56:48 +01:00
parent dafd61b5c1
commit a1520d70ff
7 changed files with 200 additions and 58 deletions

View File

@@ -153,5 +153,5 @@ export async function handleGatewayRequest(
// All handlers run inside a request scope so that plugin runtime
// subagent methods (e.g. context engine tools spawning sub-agents
// during tool execution) can dispatch back into the gateway.
await withPluginRuntimeGatewayRequestScope({ context, isWebchatConnect }, invokeHandler);
await withPluginRuntimeGatewayRequestScope({ context, client, isWebchatConnect }, invokeHandler);
}