T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- scripts/authorize.py:33
- Finding
- Device authorization exceeds the Skill's functional requirements and permits unrestricted MCP tool dispatch<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:33-36`; `scripts/mcp_client.py:1484-1504`; `scripts/mcp_client.py:1519-1524` **Vulnerability Type**: Excessive OAuth 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 MCP 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 functionality is the creation of resident-event still images. It legitimately requires image-generation operations, model discovery, relevant artifact access, and task-status reads. However, the authorization request also includes permissions for: - Video generation - Music generation - Speech generation - Reading and writing voice resources - Wallet spending - Task cancellation - General MCP tool access These permissions materially exceed the minimum privileges required for the image-only workflow. The problem is compounded by ...[truncated 1894 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Replace the shared full-scope authorization with a package-specific, least-privilege scope. For this Skill, authorize only the exact image, model, artifact, task-read, and wallet-read operations required by the documented workflow. 2. Remove unrelated permissions such as `videos:generate`, `music:generate`, `speech:generate`, `voices:write`, and `tasks:cancel` unless a concrete, user-visible feature requires them. 3. Separate wallet inspection from wallet spending. Grant spending permission only immediately before explicitly approved billable work, if the platform supports incremental authorization. 4. Add a strict local allowlist to `_run_command`, for example: - `beatra.models.list` - `beatra.images.generate` - `beatra.images.edit` - `beatra.tasks.get` - `beatra.tasks.list` - `beatra.wallet.get` - `beatra.wallet.ledger` - Any narrowly required upload operation 5. Reject all other tool names before opening an MCP session. 6. Require explicit user confirmation for each billable generation and destructive operation, including task cancellation. 7. Avoid sharing one full-scope token among unrelated Skills. Use per-package or capability-bound credentials so compromise of one package cannot exercise another package's privileges. 8. Add automated tests proving that unrelated media, voice-write, wallet-spend, and cancellation tools cannot be invoked through this package. ]]>
