T05 · Unauthorized Access and Privilege Escalation
Warning
- Location
- scripts/authorize.py:34
- Finding
- Over-Privileged Authorization and Unrestricted MCP Tool Invocation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:34-36`; `scripts/mcp_client.py:1448-1468`; `scripts/mcp_client.py:1491-1496` **Vulnerability Type**: Excessive OAuth scope and missing tool allowlist **Risk Level**: Medium ### Vulnerable Code From `scripts/authorize.py:34-36`: ```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" ) ``` From `scripts/mcp_client.py:1448-1468`: ```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}, ) ``` From `scripts/mcp_client.py:1491-1496`: ```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 is declared as a speech-generation workflow that optionally uploads a voice sample and creates a cloned voice. Its legitimate requirements include speech generation, voice access, artifact upload, task monitoring, model discovery, and limited wallet operations. The authorization request nevertheless includes unrelated privileges for image, video, and music generation. These permissions exceed the minimum privileges necessary for the declared functionality. The bundled clie ...[truncated 2080 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Replace the broad authorization scope with the minimum permissions required for this Skill. Remove at least: ```text images:generate videos:generate music:generate ``` 2. Review whether `tasks:cancel`, broad `artifacts:read`, and general `wallet:spend` are all necessary. Prefer operation-specific or package-specific scopes where supported. 3. Add a strict local allowlist before forwarding `tools/call`. The allowlist should include only documented operations, for example: ```python ALLOWED_TOOLS = { "beatra.assets.upload", "beatra.installations.register", "beatra.models.list", "beatra.speech.synthesize", "beatra.tasks.get", "beatra.tasks.list", "beatra.tasks.cancel", "beatra.voices.clone", "beatra.voices.list", "beatra.wallet.get", "beatra.wallet.ledger", } if tool_name not in ALLOWED_TOOLS: raise RuntimeError("This tool is not permitted by the New Manager Week Voice Pack") ``` 4. Separate read-only and billable capabilities. Require an explicit authorization or confirmation boundary before enabling wallet spending, cloning, speech generation, or cancellation. 5. Avoid sharing one full-scope credential across unrelated Skills. Use per-Skill or capability-constrained tokens so compromise of one package cannot reach unrelated media operations. 6. Add automated tests asserting that unrelated tools and scopes are rejected locally. ]]>
