T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- packages/plugins/openclaw-openmm/src/index.ts:133
- Finding
- State-Changing Trading Tools Do Not Enforce User Approval or Authorization## Vulnerability Details **File Location**: `packages/plugins/openclaw-openmm/src/index.ts`, lines 133-200 **Vulnerability Type**: Missing authorization and confirmation enforcement for financial operations **Risk Level**: High ### Vulnerable Code ```typescript // Create order (optional — requires explicit approval) api.registerTool( { name: "openmm_create_order", description: "Place a limit or market order. IMPORTANT: Always confirm with the user before executing.", parameters: Type.Object({ exchange: Type.String({ description: "Exchange id" }), symbol: Type.String({ description: "Trading pair, e.g. SNEK/USDT" }), side: Type.String({ description: "buy or sell" }), type: Type.String({ description: "limit or market" }), amount: Type.Number({ description: "Order amount in base currency" }), price: Type.Optional(Type.Number({ description: "Limit price (required for limit orders)" })), }), async execute( _id: string, params: { exchange: string; symbol: string; side: string; type: string; amount: number; price?: number }, ) { const args = [ "orders", "create", "--exchange", params.exchange, "--symbol", params.symbol, "--side", params.side, "--type", params.type, "--amount", String(params.amount), ]; if (params.price != null) args.push("--price", String(params.price)); return text(await openmm(args)); }, }, { optional: true }, ); // Cancel order (optional) api.registerTool( { name: "openmm_cancel_order", description: "Cancel a specific order by ID.", parameters: Type.Object({ exchange: Type.String({ description: "Exchange id" }), orderId: Type.String({ description: "Order ID to cancel" }), symbol: Type.String({ descript ...[truncated 4014 chars]
- Remediation
- ## Remediation Suggestions 1. Enforce authorization in code for every state-changing tool. Validate the authenticated OpenClaw principal and restrict access to an explicit allowlist of users, channels, and roles. 2. Implement a two-phase transaction flow: - First generate a normalized order or cancellation preview. - Return a short-lived approval identifier bound to the user, exchange, symbol, side, type, amount, price, and expiration time. - Require a second authenticated call containing that identifier before execution. 3. Apply `requireAuth` or the equivalent framework authorization control to agent tools, not only chat commands. 4. Require fresh confirmation for any changed parameter. Do not accept a generic earlier statement such as “you may trade” as approval for later transactions. 5. Enforce server-side limits for permitted exchanges, symbols, order sizes, daily notional value, price deviation, and cancellation scope. 6. Do not allow `cancel-all` without an explicit symbol unless the user separately approves an account-wide cancellation. 7. Record immutable audit events containing the authenticated actor, originating channel, approved parameters, tool invocation ID, CLI result, and exchange order IDs. Redact all credentials. 8. Keep withdrawal permissions disabled and use dedicated API keys with the minimum read/trade permissions and IP restrictions. 9. Add automated tests proving that direct calls without a valid, unexpired approval token are rejected.
