Back to skill

Security audit

UEXX Data Cloud

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a legitimate crypto market data skill, with the main caveat that it automatically contacts UEXX and stores a free API key locally.

Install only if you are comfortable with the skill contacting https://bbs.uexx.com, creating or reusing a free UEXX API key, and saving that key locally. Do not set UEXX_DATA_BASE_URL to an untrusted or non-HTTPS endpoint, and consider restricting permissions on ~/.uexx-data-cloud/free_key.json or deleting it when no longer needed.

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 (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/uexx_client.py:10
Finding
API Key Can Be Transmitted to an Arbitrary or Unencrypted Origin<![CDATA[ ## Vulnerability Details **File Location**: `scripts/uexx_client.py`, lines 10–28 **Vulnerability Type**: Unrestricted credential destination and insufficient transport validation **Risk Level**: Medium ### Vulnerable Code ```python BASE_URL = os.environ.get("UEXX_DATA_BASE_URL", "https://bbs.uexx.com").rstrip("/") STATE_DIR = Path(os.environ.get("UEXX_DATA_STATE_DIR", Path.home() / ".uexx-data-cloud")) KEY_FILE = STATE_DIR / "free_key.json" class UEXXError(RuntimeError): pass def request_json(path: str, method: str = "GET", api_key: str | None = None, body: dict[str, Any] | None = None) -> dict[str, Any]: data = None headers = {"Accept": "application/json"} if api_key: headers["X-API-Key"] = api_key if body is not None: data = json.dumps(body).encode("utf-8") headers["Content-Type"] = "application/json" req = urllib.request.Request(BASE_URL + path, data=data, headers=headers, method=method) ``` ### Technical Analysis The API base URL is taken directly from the `UEXX_DATA_BASE_URL` environment variable without validation of its scheme, hostname, port, or trust level. The same request function attaches the locally cached API key to the `X-API-Key` header and sends it to the configured destination. Although sending an API key to the declared UEXX service is necessary for authenticated market-data queries, allowing the credential destination to be replaced by any environment-provided URL exceeds the minimum privilege required for normal operation. A value using `http://` would also transmit the credential without TLS protection. Exploitation requires influence over the process environment or its launcher configuration. This is a meaningful trust-boundary issue in shared automation, CI, plugin hosts, or agent runtimes where environment settings may be inherited from a less-trusted source. ### Attack Path 1. The Skill has already obtained and cached a valid Free API key. 2. An attacker or compromi ...[truncated 852 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Pin authenticated production requests to `https://bbs.uexx.com`. - If a configurable base URL is required for development, require an explicit development-mode opt-in. - Parse the URL before use and enforce: - The `https` scheme. - An allowlisted hostname. - An expected port. - No embedded user information. - Attach `X-API-Key` only when the final request origin exactly matches an approved credential destination. - Reject or tightly control cross-origin redirects for authenticated requests. - Keep separate credentials for production and development endpoints. - Fail closed with a clear error if the configured URL does not satisfy the trust policy. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/uexx_client.py:40
Finding
Persisted API Key Does Not Have Explicitly Restricted File Permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/uexx_client.py`, lines 40–43 **Vulnerability Type**: Insecure local credential storage permissions **Risk Level**: Low ### Vulnerable Code ```python def save_key(payload: dict[str, Any]) -> None: STATE_DIR.mkdir(parents=True, exist_ok=True) payload = dict(payload) payload["saved_at"] = time.time() KEY_FILE.write_text(json.dumps(payload, ensure_ascii=False, indent=2), encoding="utf-8") ``` ### Technical Analysis The Skill persists the API response, including `api_key`, in `~/.uexx-data-cloud/free_key.json`. Neither the state directory nor the key file is created with an explicit restrictive mode. Their effective permissions therefore depend on the process umask and existing filesystem state. Under a permissive umask, the directory or file may be readable by other local users. In addition, if the path already exists with overly broad permissions, `write_text()` does not correct them. Persisting the key is consistent with the declared key-reuse workflow, but securely restricting access is necessary to preserve least privilege. ### Attack Path 1. The Skill requests a Free API key from the declared service. 2. `save_key()` creates the state directory and writes `free_key.json` while the process has a permissive umask, or it overwrites a file that already has broad permissions. 3. Another local account or process with filesystem access reads the JSON file. 4. The account extracts the `api_key` value. 5. The disclosed key is reused to access the UEXX API or consume its quota. ### Impact Assessment The exposed privilege is limited to the access granted by the stored UEXX Free API key. A local attacker could issue requests under that key or exhaust associated quotas. The reviewed code does not indicate that the file contains unrelated operating-system, cloud, wallet, or exchange credentials. Exploitation also requires local filesystem access and permissive effective permissions. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions - Create the state directory with mode `0700`. - Create the key file with mode `0600`, using APIs that set permissions at creation time. - Correct permissions on existing directories and files before reading or writing credentials. - Write through a securely created temporary file in the same directory and atomically replace the destination. - Avoid following symbolic links when creating or replacing the credential file. - Consider storing only the fields required for reuse rather than the entire key-issuance response. - Where supported, use an operating-system credential store instead of a plaintext JSON file. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (13)

Tainted flow: 'req' from os.environ.get (line 27, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
headers["Content-Type"] = "application/json"
    req = urllib.request.Request(BASE_URL + path, data=data, headers=headers, method=method)
    try:
        with urllib.request.urlopen(req, timeout=30) as response:
            return json.loads(response.read().decode("utf-8"))
    except urllib.error.HTTPError as exc:
        try:
Confidence
92% confidence
Finding
The request destination is derived from the UEXX_DATA_BASE_URL environment variable and then used directly for outbound HTTP requests, including requests that may carry the X-API-Key header. If an attacker can influence the runtime environment, they can redirect traffic to an attacker-controlled host and capture issued API keys or manipulate responses, creating an SSRF-style exfiltration and trust-boundary violation. In this skill context, automatic key acquisition and authenticated requests make the issue more dangerous because the code will willingly send credentials to the configured endpoint without validating it.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The declared description says the skill should serve end-user cryptocurrency data queries and automatically manage API-key usage to provide direct answers from a cached market data service. However, this code only calls a public '/api/v1/public/api-guide' endpoint, extracts 'data_catalog' and 'catalog_summary', and prints them. That is a materially different primary purpose: catalog/documentation discovery rather than market-data querying, sentiment/funding/OI retrieval, or direct answer generation. No API-key acquisition/reuse logic or market-data retrieval is present in this chunk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
The code generally aligns with the UEXX Data Cloud market-data querying purpose, especially for sentiment-like metrics (fear-greed, altcoin-season) and derivatives metrics (funding rate, OI, long/short ratios). However, the declared description is broader than what this code actually implements. There is no ETF flow endpoint in the supplied chunk, and the phrase 'query cryptocurrency market data' suggests wider coverage than the five hard-coded endpoints. Additionally, the claim that the skill automatically obtains or reuses a free API key is not evidenced here; authentication may happen elsewhere, but this chunk does not demonstrate it. Because the implemented scope is materially narrower than the declared capabilities, this should be flagged as a mismatch.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The README presents the skill description and user interaction model entirely in Chinese, including the example prompts the user is expected to use, with no indication that other languages are supported or that Chinese is an intentional region-specific requirement. Per the policy, forcing a specific language without user opt-in is a natural-language policy concern.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The README states that the skill will automatically request a Free API key from a remote service and persist it locally, but it does not clearly warn users that network requests will be made on their behalf or that a credential will be stored under their home directory. In an agent skill context, silent credential acquisition and persistence can violate user expectations, create privacy concerns, and leave reusable secrets on disk where other local processes or users may access them.

Lp3

Medium
Category
MCP Least Privilege
Confidence
81% confidence
Finding
The skill declares behavior that relies on file access, environment use, and outbound network activity, but it does not declare any explicit tool scope or permissions boundary. In an agent setting, missing scope declarations can cause over-broad execution privileges and make it harder for users or orchestrators to understand that external requests and local resource access may occur.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill explicitly instructs automatic acquisition or reuse of an API key and outbound requests to a third-party service without warning the user that data will be transmitted externally. In agent environments, silent external calls can leak user queries, symbols of interest, or metadata, and automatic credential handling reduces user visibility into when authentication and data sharing occur.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The default prompt hard-codes a Chinese-language query ("今日恐慌指数多少?") without any indication that the user requested Chinese output. This can steer invocation behavior and responses into a language the user did not choose, creating confusing or misleading UX and potentially causing unintended tool use patterns in multilingual contexts.

Missing User Warnings

Medium
Confidence
86% confidence
Finding
The client automatically transmits the API key in an HTTP header to the configured external service, and there is no in-code restriction ensuring the destination is a trusted HTTPS endpoint. While sending an API key to the legitimate API is expected behavior, the lack of destination validation means this becomes credential disclosure if BASE_URL is redirected or downgraded. The skill context increases risk because authenticated requests are automatic and invisible to the user.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The code stores the free API key in a predictable file under the user's home directory without setting restrictive permissions or providing any disclosure. On multi-user systems, shared environments, or improperly permissioned home directories, this can expose the credential to other local users or processes. In this skill, the persistence is automatic, so users may not realize a credential has been written to disk at all.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
This POST request contacts an external service to create a free API key, which affects user privacy/network behavior and may create server-side state. The code contains no prompt, log, or comment disclosing that it will reach out to a third-party endpoint for account/key provisioning.

Natural-Language Policy Violations

Low
Confidence
77% confidence
Finding
The answer-style section includes a Chinese-only example, which can signal a language preference or default output behavior. Since no opt-in, language choice, or region-specific justification is provided elsewhere in the file, this may violate language/locale neutrality expectations.

Missing User Warnings

Low
Confidence
90% confidence
Finding
The skill instructs automatic acquisition and use of a third-party API key but does not disclose that requests expose the user's or operator's IP address to an external service and may allow the provider to log key usage patterns. In a skill that defaults to contacting the external API on the user's behalf, this creates a real privacy and transparency issue even if it is not a direct code-execution or credential-theft vulnerability.

Static analysis

No suspicious patterns detected.