T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- scripts/authorize.py:34
- Finding
- Overprivileged Device Token Combined with Unrestricted MCP Tool Dispatch<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:34-36`; `scripts/mcp_client.py:1438-1468` **Vulnerability Type**: Excessive authorization scope and missing tool allowlist **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 command dispatcher accepts 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}, ) ``` ```python call = subparsers.add_parser("call", help="Call one tool with a JSON object on stdin") call.add_argument("tool_name") ``` ### Technical Analysis The declared Skill workflow requires asset upload, model and voice discovery, optional voice cloning, speech synthesis, video generation, task status access, and limited wallet information. The authorization request additionally includes image generation, music generation, broad voice-writing, wallet spending, and task cancellation. At the same time, the bundled client does not enforce a package-specific allowlist. Any value supplied as `tool_name` is forwarded to the authenticated MCP endpoint through `tools/call`. Consequently, the local client does not prevent the ...[truncated 1911 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Replace the shared full-scope credential with a package-specific, least-privilege token. 2. Remove scopes not required by this Skill, particularly: - `images:generate` - `music:generate` - Broad `voices:write` access unless narrowly required for the optional clone operation - `tasks:cancel` unless cancellation is explicitly enabled for the current workflow 3. Separate wallet read access from spending authority. A read-only balance or ledger operation should not require a general `wallet:spend` capability. 4. Add a strict local allowlist before dispatching `tools/call`. The allowlist should contain only the tools required by the documented workflow, such as: - `beatra.assets.upload` - `beatra.models.list` - `beatra.voices.list` - `beatra.voices.clone` - `beatra.speech.synthesize` - `beatra.videos.animate` - `beatra.tasks.get` - `beatra.tasks.list` - `beatra.tasks.cancel`, only when explicitly justified - Required read-only wallet operations - `beatra.installations.register` 5. Reject unknown tool names locally before creating an authenticated MCP session. 6. Consider separate short-lived capability grants for paid clone, speech, and video stages so approval for one stage cannot authorize unrelated operations. 7. Add automated tests proving that unrelated tools, including music and generic image-generation tools, are rejected locally. ]]>
