T05 · Unauthorized Access and Privilege Escalation
- Location
- scripts/authorize.py:35
- Finding
- Voicemail Skill Requests Excessive OAuth Privileges and Permits Arbitrary MCP Tool Calls<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:35-38`; `scripts/mcp_client.py:1461-1485` **Vulnerability Type**: Excessive authorization scope and unrestricted remote tool dispatch **Risk Level**: Medium ### Vulnerable Code The authorization helper requests capabilities unrelated to voicemail generation: ```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 caller-supplied MCP tool name without applying a Skill-specific allowlist: ```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}, ) ``` The command-line interface exposes the unrestricted tool name directly: ```python call = subparsers.add_parser("call", help="Call one tool with a JSON object on stdin") call.add_argument("tool_name") ``` ### Technical Analysis The Skill’s declared functionality requires text-to-speech generation, optional voice cloning, explicit sample upload, voice and model discovery, task inspection, and limited billing information. The requested bearer-token scope additionally grants image, video, and music generation, general artifact access, wallet spending, and task cancellation. ...[truncated 1980 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Replace the shared broad scope with a least-privilege scope limited to: - Text-to-speech generation. - Voice and model lookup. - Optional voice cloning only when requested. - Explicit artifact upload for authorized voice samples. - Task status and result retrieval. - Read-only wallet balance and ledger operations where required. 2. Remove unrelated permissions such as image, video, and music generation from this Skill’s authorization request. 3. Avoid granting general wallet spending and task cancellation unless a specific documented workflow requires them. 4. Introduce a Skill-specific allowlist in `_run_command`, for example: - `beatra.models.list` - `beatra.voices.list` - `beatra.voices.clone` - `beatra.speech.synthesize` - `beatra.assets.upload` - `beatra.tasks.get` - `beatra.tasks.list` - `beatra.wallet.get` - `beatra.wallet.ledger` 5. Reject all tools not explicitly permitted for this package before initiating the MCP request. 6. Use separate authorization grants for optional high-risk capabilities, such as voice cloning or task cancellation. 7. Require explicit user confirmation immediately before paid or destructive operations, independently of the initial device authorization. 8. Prefer per-package credentials over a shared bearer credential so compromise of one Skill does not expose unrelated Beatra capabilities. ]]>
