T09 · Insecure Skill Coding Practices
- Location
scripts/mcp_client.py:2299- Finding
Paid MCP Operations Lack an Enforceable User-Approval Gate
- Content
View full analysis
Vulnerability Details
File Location:
scripts/mcp_client.py:2299-2317,scripts/mcp_client.py:2382-2384
Vulnerability Type: Missing authorization enforcement for chargeable operations
Risk Level: HighRelevant Code:
python def _run_command( command: str, tool_name: str | None = None, arguments: dict[str, Any] | None = None, ) -> dict[str, Any]: session = _session_with_registration( state_dir=Path.home() / ".beatra", post_json=_default_post_json, ) if command == "tools": return session.request(2, "tools/list", {}) if arguments is None: arguments = _read_tool_arguments() assert tool_name is not None return session.request( 2, "tools/call", {"name": tool_name, "arguments": arguments}, )python call = subparsers.add_parser("call", help="Call one tool with a JSON object on stdin") call.add_argument("tool_name")Technical Analysis
The bundled client accepts an arbitrary MCP tool name through a command-line argument and an arbitrary argument object through standard input. It then forwards both through an authenticated
tools/callrequest without distinguishing read-only tools from paid or state-changing tools.The authorization scope declared in
scripts/authorize.py:43-46includeswallet:spend, media-generation, write, and task-cancellation capabilities. Consequently, possession of the existing Device Token gives this generic call path access to operations capable of consuming credits or changing remote state.The Skill documentation establishes two explicit user-approval stages before paid generation. In particular,
references/workflow.md:120-123states that approved preparation does not authorize video generation and that submission must wait until the user confirms sufficient credits or a top-up. These controls are only prose instructions. The executable ...[truncated 2016 chars]- Remediation
View remediation
Remediation Suggestions
- Classify all supported MCP tools as read-only, free state-changing, paid, or destructive.
- Reject paid and destructive tools in the generic
callpath unless an executable approval check succeeds. - Before approval, generate a canonical representation and cryptographic digest of the exact tool name, model, artifacts, duration, estimated maximum charge, and other request arguments.
- Require a short-lived approval receipt bound to that digest, the authenticated installation, and a single
client_request_id. - Reject the request if any argument differs from the approved payload or if the receipt is expired or already consumed.
- Restrict this Skill to an explicit allowlist of required Beatra tools rather than forwarding arbitrary tool names.
- Keep read-only discovery and balance operations separate from spending operations.
- Add tests proving that direct paid calls fail without approval, changed payloads invalidate approval, and preparation approval cannot authorize a video request.
