T05 · Unauthorized Access and Privilege Escalation
Warning
- Location
- scripts/authorize.py:31
- Finding
- Overprivileged Device Token and Unrestricted MCP Tool Dispatch<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:31-34`; `scripts/mcp_client.py:1458-1489` **Vulnerability Type**: Excessive authorization scope and unrestricted use of remote tools **Risk Level**: Medium ### Vulnerable Code Authorization requests capabilities unrelated to the declared rental walk-in workflow: ```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 interface accepts an arbitrary MCP tool name without enforcing a package-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 CLI exposes that arbitrary tool-name parameter 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 declared workflow requires artifact upload, model discovery, voice listing or cloning, speech generation, video generation, task reads, optional task cancellation, and wallet queries. It does not require music generation or independent image generation. Nevertheless, authorization requests `music:generate` and `images:generate`, along with the broad `mcp:tools` ...[truncated 2290 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Replace the shared full-scope authorization with a package-specific, least-privilege grant. 2. Remove capabilities not required by this Skill, particularly: - `images:generate` - `music:generate` 3. Narrow generic capabilities such as `mcp:tools` and `wallet:spend` where the service supports more granular scopes. 4. Add a strict local allowlist before dispatching `tools/call`. It should contain only the operations 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` - `beatra.wallet.get` - `beatra.wallet.ledger` - `beatra.installations.register` 5. Reject every unrecognized tool name before initializing or contacting the remote service. 6. Separate read-only, upload, and billable capabilities into distinct tokens or grants where supported. 7. Preserve the existing explicit confirmation requirements for paid clone, speech, and video stages, and enforce those boundaries in code rather than relying only on Skill instructions. 8. Add automated tests proving that unrelated tools, including image and music generation, cannot be invoked through this package. ]]>
