T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- scripts/authorize.py:31
- Finding
- Authorization Requests Capabilities Beyond the Skill's Declared Functionality<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:31-38`; related unrestricted dispatch at `scripts/mcp_client.py:1463-1480` **Vulnerability Type**: Excessive OAuth scope and unrestricted remote tool dispatch **Risk Level**: High ### Vulnerable Code ```python SCOPE = ( "mcp:tools artifacts:write images:generate videos:generate music:generate " "speech:generate voices:read voices:write wallet:spend tasks:read artifacts:read tasks:cancel" ) ``` The MCP client also allows the caller to supply an arbitrary remote tool name: ```python def _run_command(command: str, tool_name: str | 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", {}) try: arguments = json.load(os.sys.stdin) except json.JSONDecodeError as exc: raise RuntimeError("Tool arguments on stdin must be one JSON object") from exc if not isinstance(arguments, dict): raise RuntimeError("Tool arguments on stdin must be one JSON object") assert tool_name is not None return session.request( 2, "tools/call", {"name": tool_name, "arguments": arguments}, ) ``` ### Technical Analysis The Skill's declared purpose is to create game UI voice clips. Its legitimate requirements include speech synthesis, optional voice cloning and sample upload, voice/model lookup, task status reads, and limited billing visibility. The requested authorization scope additionally includes: - Image generation - Video generation - Music generation - Broad artifact read and write access - Wallet spending - Task cancellation - General MCP tool access These permissions are not all necessary to generate UI voice clips. In addition, the bundled client does not enforce a local allowlist of tools appropriate to this package. Any tool name supplied through ...[truncated 1690 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Define a package-specific OAuth scope containing only the operations required for UI voice generation. 2. Remove image, video, and music generation permissions from this Skill. 3. Separate optional voice cloning and asset upload permissions from baseline speech synthesis, requesting them only when the user chooses those features. 4. Replace unrestricted wallet spending with a narrowly scoped permission limited to explicitly confirmed speech or cloning operations, if the service supports it. 5. Enforce a local allowlist in `mcp_client.py`, such as: - `beatra.models.list` - `beatra.voices.list` - `beatra.voices.clone` - `beatra.speech.synthesize` - `beatra.assets.upload` - `beatra.tasks.get` - `beatra.tasks.list` - `beatra.tasks.cancel` only after explicit user authorization - Required read-only wallet operations 6. Reject any tool name outside the allowlist before reading or forwarding arguments. 7. Use separate credentials per Skill where practical so compromise of one package cannot affect every Beatra package installed on the device. 8. Display the exact requested scopes on the approval page in user-readable terms. ]]>
