T09 · Insecure Skill Coding Practices
- Location
scripts/mcp_client.py:2299- Finding
Arbitrary authenticated MCP tool calls bypass the documented approval gate
- Content
View full analysis
Vulnerability Details
File Location:
scripts/mcp_client.py:2299-2316, 2383, 2475; authorization requirement documented atSKILL.md:37
Vulnerability Type: Missing authorization enforcement for authenticated and potentially billable operations
Risk Level: HighComplete Code Snippet
python def _run_command( command: str, tool_name: str | None = None, arguments: dict[str, Any] | 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", {}) if arguments is None: arguments = _read_tool_arguments() assert tool_name is not None return session.request( 2, "tools/call", {"name": tool_name, "arguments": arguments}, )The command parser accepts an unrestricted tool name:
python call = subparsers.add_parser("call", help="Call one tool with a JSON object on stdin") call.add_argument("tool_name")It is then invoked directly:
python elif args.command in {"tools", "call"}: arguments = _read_tool_arguments() if args.command == "call" else None result = _with_waiting_approval( lambda: _run_command(args.command, getattr(args, "tool_name", None), arguments), state_dir=state_dir, )By contrast,
SKILL.md:37requires an admission card and explicit confirmation before submitting the paid video operation:text Do not submit until the user confirms they have topped up or already have enough credits for this estimate.Technical Analysis
The CLI treats both the MCP tool name and its JSON arguments as caller-controlled values.
_run_commandestablishes an authenticated session using the shared Device Token and forwards those values totools/callwithout:- restrictin ...[truncated 2242 chars]
- Remediation
View remediation
Remediation Suggestions
- Replace unrestricted tool dispatch with a package-specific allowlist containing only tools required by this Skill.
- Separate read-only operations from billable and state-changing operations.
- Require a short-lived confirmation artifact for every billable or destructive call. Bind it cryptographically or structurally to:
- the exact tool name;
- canonicalized arguments;
- the estimated charge;
- the stable
client_request_id; - the user or installation identity;
- a narrow expiration time.
- Reject any change to the approved payload and require fresh approval.
- Enforce one-time use for approval artifacts where appropriate.
- Prefer narrower OAuth scopes for this package rather than relying on one broad shared token.
- Add tests proving that direct CLI invocation cannot submit a paid generation, cancel a task, or invoke unrelated tools without valid approval.
