T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- scripts/authorize.py:35
- Finding
- Overprivileged Device Token and Unrestricted MCP Tool Dispatch## Vulnerability Details **File Location**: `scripts/authorize.py:35-39`; `scripts/mcp_client.py:1463-1482` **Vulnerability Type**: Excessive authorization scope and missing tool allowlist **Risk Level**: High ### Vulnerable Code `scripts/authorize.py:35-39`: ```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" ) ``` `scripts/mcp_client.py:1463-1482`: ```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 function is to create customer-onboarding voice clips and, when explicitly requested, clone a voice from an authorized sample. The requested OAuth scope nevertheless includes unrelated image, video, and music generation capabilities. It also grants credit spending and task cancellation. The bundled client accepts any caller-provided MCP tool name and forwards it through `tools/call`. There is no package-specific allowlist limiting execution to the tools required by the documented voice workflow. Consequently, the effective authorization boundary is the broad server-issued token rather than the narrower set of op ...[truncated 1675 chars]
- Remediation
- ## Remediation Suggestions 1. Replace the shared full-scope token with a package-specific token limited to the voice workflow. 2. Remove `images:generate`, `videos:generate`, and `music:generate`. 3. Grant only the narrowly required speech, voice, model-discovery, upload, artifact-read, and task-read capabilities. 4. Separate wallet spending and task cancellation into explicit, user-approved elevation steps if those privileges are ever required. 5. Add a strict local MCP tool allowlist, for example: - `beatra.models.list` - `beatra.voices.list` - `beatra.voices.clone` - `beatra.speech.synthesize` - `beatra.assets.upload` - `beatra.tasks.get` - `beatra.tasks.list` - Required read-only wallet operations 6. Reject every unrecognized tool name before loading or transmitting credentials. 7. Ensure server-side policy independently enforces the same package-specific allowlist. 8. Use separate credentials for different installed Skills rather than sharing one full-scope token.
