T05 · Unauthorized Access and Privilege Escalation
Error
- Location
- scripts/authorize.py:34
- Finding
- Image-only Skill obtains an excessively broad shared bearer credential<![CDATA[ ## Vulnerability Details **File Location**: `scripts/authorize.py:34-37` **Vulnerability Type**: Excessive OAuth scopes and missing client-side tool restrictions **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 requested scope is passed directly into the Device Authorization request at `scripts/authorize.py:449-459`: ```python form: dict[str, str] = { "client_id": CLIENT_ID, "resource": MCP_URL, "scope": SCOPE, "platform": host_platform, "client_name": PACKAGE_DISPLAY_NAME, "external_installation_ref": external_reference, "package_version": PACKAGE_VERSION, "package_slug": PACKAGE_SLUG, } ``` The generic client also permits an arbitrary tool name at `scripts/mcp_client.py:1459-1481`: ```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 declared function of this Skill is to produce lyric-card still images. Its legitimate operations include model lookup, image generation and editing, optional artifact upload, task status management, and limited wallet inspection. The requested bearer credential addition ...[truncated 2378 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Replace the shared full-scope credential with a package-specific, least-privilege credential. 2. Restrict authorization to the exact operations required by this Skill, such as: - Model metadata lookup for image generation. - Image generation and image editing. - Explicitly approved artifact upload. - Task read and narrowly scoped cancellation. - Read-only wallet balance and ledger access. 3. Remove `videos:generate`, `music:generate`, `speech:generate`, and `voices:write` from this package’s authorization request. 4. Replace generic `wallet:spend` with a capability limited to approved image operations, if supported by the service. 5. Add a client-side allowlist for MCP tools. Reject any tool name not required by the documented workflow. 6. Bind server-side permissions to the package identity and validate that the requested tool is permitted for `music-lyric-set`. 7. Avoid sharing one broad bearer credential among unrelated Skills. Use independently revocable credentials with separate audit trails. 8. Add automated tests asserting that unrelated video, music, speech, and voice tools cannot be called using this Skill’s credential. ]]>
