Back to skill

Security audit

Super Mcp Client 1.0.3

Security checks for vulnerabilities and agentic risk

Overview

This is a user-directed MCP client whose network and resource access match its stated purpose, with credential and remote-server cautions users should understand.

Install only if you intend to connect to MCP servers you control or trust. Prefer HTTPS for any non-local server, avoid passing sensitive values in tool arguments or resource URIs, and avoid putting long-lived API keys directly on the command line.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T09 · Insecure Skill Coding Practices

Warning
Location
mcp_client.py:17
Finding

Bearer API Credentials May Be Transmitted over Plaintext HTTP

Content
View full analysis

Vulnerability Details

File Location: mcp_client.py, lines 17–25
Vulnerability Type: Transmission of sensitive information over an insecure channel
Risk Level: Medium

Vulnerable Code

python
DEFAULT_MCP_SERVER = "http://localhost:8080"


class MCPClient:
    """Client for Model Context Protocol"""
    
    def __init__(self, server_url=DEFAULT_MCP_SERVER, api_key=None):
        self.server_url = server_url.rstrip("/")
        self.session = requests.Session()
        if api_key:
            self.session.headers["Authorization"] = f"Bearer {api_key}"

The server URL is user-configurable, and the client does not require HTTPS before adding the supplied API key to the session's Authorization header. Although the default endpoint is a loopback address, callers can provide a non-loopback http:// endpoint without receiving a warning or having the request rejected.

Technical Analysis

Bearer tokens grant access to whoever possesses them. When the client communicates with a remote server over plaintext HTTP, the authorization header is not protected by transport encryption. An attacker with visibility or control over the network path can inspect or modify the request and recover the API key.

TLS certificate verification is enabled by default in requests for HTTPS endpoints, but this protection does not apply when the configured URL uses HTTP. The issue therefore becomes exploitable when a user supplies an API key together with a plaintext, non-loopback server URL.

Attack Path

  1. A user is instructed to connect to a remote MCP endpoint using an http:// URL.
  2. The user supplies an API key to MCPClient or through the CLI.
  3. The constructor places the key in the session-wide Authorization: Bearer header.
  4. A client method sends a request to the plaintext endpoint.
  5. An attacker controlling or observing the network path captures the authorization header.
  6. The attacke ...[truncated 431 chars]
Remediation
View remediation

Remediation Suggestions

  • Require an https:// URL whenever an API key is configured.
  • Allow plaintext HTTP only for explicitly recognized loopback addresses, such as 127.0.0.1, ::1, and localhost.
  • If remote plaintext access is operationally necessary, require an explicit option such as --allow-insecure-http and display a prominent warning.
  • Parse and validate the URL with urllib.parse.urlparse instead of relying on string-prefix checks.
  • Continue using the default TLS certificate verification behavior and do not introduce a general certificate-verification bypass.
  • Avoid forwarding authorization headers if future code permits redirects to a different origin; explicitly constrain redirects or reject cross-origin redirects for authenticated requests.

T09 · Insecure Skill Coding Practices

Note
Location
mcp_client.py:109
Finding

API Key Accepted Directly through Command-Line Arguments

Content
View full analysis

Vulnerability Details

File Location: mcp_client.py, lines 109–112
Vulnerability Type: Local exposure of credentials through process arguments and shell history
Risk Level: Low

Vulnerable Code

python
# Parent parser for global args
parent_parser = argparse.ArgumentParser(add_help=False)
parent_parser.add_argument("--server-url", default=DEFAULT_MCP_SERVER, help="MCP Server URL")
parent_parser.add_argument("--api-key", help="API Key")

Technical Analysis

Supplying a secret as a command-line argument can expose it outside the client process. Depending on the operating system and shell configuration, complete commands may be retained in shell history, process accounting, terminal logs, automation logs, or diagnostic output. Process arguments may also be readable by other local users or monitoring tools while the process is running.

The key is not hardcoded and is not deliberately logged by the Python code. The risk arises specifically from the secret-input mechanism and therefore depends on the host's process visibility, shell, and logging configuration.

Attack Path

  1. A user runs the client with a command such as python mcp_client.py tools --api-key SECRET.
  2. The shell records the command in history, an automation platform records it in a job log, or the operating system exposes it in the process argument list.
  3. Another local user, administrator, monitoring service, or person with access to the relevant logs retrieves the argument.
  4. The recovered bearer token is reused against the corresponding MCP server.

Impact Assessment

An attacker who recovers the argument obtains the privileges associated with the API key. Those privileges may include MCP tool invocation and access to server resources. Exploitation ordinarily requires local process visibility, access to shell history, or access to execution logs; this issue does not independently provide remote code execution or ele ...[truncated 34 chars]

Remediation
View remediation

Remediation Suggestions

  • Prefer a protected environment variable or configuration file with restrictive filesystem permissions.
  • Support interactive secret entry using getpass.getpass() so the key is not echoed or placed in process arguments.
  • For automation, support reading the token from standard input or from a caller-provided credential file descriptor.
  • Deprecate direct use of --api-key, or make it an explicit compatibility option that emits a warning about process-list and shell-history exposure.
  • Ensure error messages and diagnostic logging never print the authorization header or supplied credential.
  • Document token rotation and revocation procedures in case a key is exposed.

T09 · Insecure Skill Coding Practices

Note
Location
mcp_client.py:27
Finding

HTTP Requests Lack Connection and Read Timeouts

Content
View full analysis

Vulnerability Details

File Location: mcp_client.py, lines 27–69
Vulnerability Type: Unbounded network operation enabling denial of service
Risk Level: Low

Vulnerable Code

python
def connect(self):
    """Connect to MCP server"""
    resp = self.session.get(f"{self.server_url}/mcp/connect")
    resp.raise_for_status()
    return resp.json()

def list_tools(self):
    """List available tools"""
    resp = self.session.get(f"{self.server_url}/mcp/tools")
    resp.raise_for_status()
    return resp.json()

def call_tool(self, tool_name, arguments):
    """Call a tool"""
    data = {
        "tool": tool_name,
        "arguments": json.loads(arguments) if isinstance(arguments, str) else arguments
    }
    resp = self.session.post(f"{self.server_url}/mcp/call", json=data)
    resp.raise_for_status()
    return resp.json()

def list_resources(self):
    """List available resources"""
    resp = self.session.get(f"{self.server_url}/mcp/resources")
    resp.raise_for_status()
    return resp.json()

def read_resource(self, resource_uri):
    """Read a resource"""
    # Security: Warn about file:// URIs (could exfiltrate local files)
    if resource_uri.startswith("file://"):
        print("WARNING: file:// URIs can read local files from the MCP server.", file=sys.stderr)
        print("Only use with trusted MCP servers.", file=sys.stderr)
    resp = self.session.get(f"{self.server_url}/mcp/read?uri={resource_uri}")
    resp.raise_for_status()
    return resp.json()

def list_prompts(self):
    """List prompt templates"""
    resp = self.session.get(f"{self.server_url}/mcp/prompts")
    resp.raise_for_status()
    return resp.json()

Technical Analysis

The requests library does not impose a timeout unless one is explicitly supplied. Every HTTP operation in this client omits the timeout argument. Consequently, a server can accept a c ...[truncated 1156 chars]

Remediation
View remediation

Remediation Suggestions

  • Set explicit connection and read timeouts on every request, for example timeout=(5, 30).
  • Centralize request handling in a helper method or configure a custom session adapter so new methods cannot accidentally omit timeouts.
  • Catch requests.exceptions.Timeout, provide a concise error, and exit or return a controlled failure.
  • Apply carefully bounded retries only to idempotent operations; avoid automatically retrying tool-invocation POST requests unless the protocol supplies an idempotency mechanism.
  • Allow timeout values to be configured within safe minimum and maximum bounds for deployments with different latency requirements.
  • Add tests using a server that accepts connections but delays its response to verify bounded termination.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (3)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill exposes MCP and network capabilities but does not declare any explicit tool scope or permission boundaries. Because this skill is specifically designed to connect to arbitrary remote MCP servers and access tools, resources, and file-backed URIs, the missing scope significantly increases the risk of unintended network access, remote capability invocation, and sensitive data exposure through overly broad agent execution.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The call_tool method posts the selected tool name and provided arguments to a remote MCP server, which can transmit potentially sensitive user or system data over the network. Although the code is a client by purpose, there is no confirmation, logging, or warning in this path to disclose that the supplied arguments are being sent to the server.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The read_resource method forwards arbitrary resource URIs to the MCP server, but warns only for file:// URIs even though other schemes or sensitive identifiers may also trigger access to confidential server-side or backend-connected resources. In the context of an MCP client that brokers access to external tools and data sources, this limited warning can mislead users into underestimating the privacy and data-exposure risks of non-file resources.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.