T05 · Unauthorized Access and Privilege Escalation
Warning
- Location
- scripts/authorize.py:34
- Finding
- Mnemonic-song authorization grants unrelated cross-media and account privileges<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:34-37`; unrestricted tool dispatch at `scripts/mcp_client.py:1465-1480` **Vulnerability Type**: Excessive authorization scope and missing local tool allowlist **Risk Level**: Medium ### 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 generic command dispatcher accepts any MCP tool name supplied to it: ```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 generate exam mnemonic songs. Its legitimate requirements include music generation, relevant model and task reads, billing access, and user-requested task cancellation. The authorization scope additionally grants: - Image generation - Video generation - Speech generation - Voice reading and modification - Broad artifact read and write access - Wallet spending - General MCP tool access These permissions are not required to create mnemonic songs. The broad scope is particularly significant because `mcp_client.py call` does not restrict the supplied tool name to the operations documented by this Skill. Consequently ...[truncated 1838 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Replace the shared cross-media scope with a package-specific, least-privilege scope containing only: - Music generation - Required model metadata reads - Task reads - User-requested task cancellation - Minimum billing or wallet operations required by the documented workflow 2. Remove image, video, speech, and voice privileges from this Skill's authorization request. 3. Separate artifact permissions into narrowly scoped operations and grant them only if this Skill actually needs artifact transfer. 4. Avoid a general `wallet:spend` capability where the service can instead authorize only approved music-generation operations. 5. Add a local allowlist in `_run_command` and reject all other tool names. The allowlist should include only documented operations such as: - `beatra.models.list` - `beatra.music.generate` - `beatra.tasks.get` - `beatra.tasks.list` - `beatra.tasks.cancel` - Required read-only wallet operations - Installation registration, if retained 6. Enforce the same package-level restrictions on the server so bypassing the local client cannot recover the broader capabilities. 7. Display the exact requested privileges on the authorization page in user-understandable terms. 8. Use separate credentials for separate Skills rather than sharing one full-scope token across unrelated media packages. ]]>
