T09 · Insecure Skill Coding Practices
- Location
addon/FreeCADMCP/rpc_server/rpc_server.py:168- Finding
Unauthenticated Arbitrary Python Code Execution in the FreeCAD Process
- Content
View full analysis
dict[str, Any]: output_buffer = io.StringIO() def task(): try: with contextlib.redirect_stdout(output_buffer): exec(code, globals()) FreeCAD.Console.PrintMessage("Python code executed successfully.\n") return True except Exception as e: FreeCAD.Console.PrintError( f"Error executing Python code: {e}\n" ) return f"Error executing Python code: {e}\n" ``` The RPC service registers the method without authentication or authorization: ```python rpc_server_instance = SimpleXMLRPCServer( (host, port), allow_none=True, logRequests=False ) rpc_server_instance.register_instance(FreeCADRPC()) def server_loop(): FreeCAD.Console.PrintMessage(f"RPC Server started at {host}:{port}\n") rpc_server_instance.serve_forever() ``` The same capability is exposed directly as an MCP tool: ```python @mcp.tool() def execute_code(ctx: Context, code: str) -> list[TextContent | ImageContent]: """Execute arbitrary Python code in FreeCAD. ``` ### Technical Analysis Caller-controlled input reaches Python's `exec()` with the FreeCAD process globals. There is no authentication, authorization, source validation, user confirmation, restricted built-in environment, process isolation, or allowlist of permitted operations. Although the XML-RPC service binds to `localhost` by default, any local process able to connect to port `9875` can invoke the method. The MCP layer also exposes the same primitive to any client with access to the MCP server. An attacker who compromises or influences an MCP client, includ ...[truncated 1994 chars]- Remediation
View remediation
