Back to skill

Security audit

Cex Trader

Security checks for vulnerabilities and agentic risk

Overview

This is a real trading skill, but it needs Review because it handles exchange API secrets and live trading commands through a configurable MCP endpoint without enough transport, destination, or confirmation guardrails.

Review carefully before installing. Only use this with a trusted MCP server over HTTPS, withdrawal-disabled and tightly scoped exchange API keys, IP allowlists where possible, and small test balances or sandbox mode first. Avoid putting exchange secrets on the command line, and require explicit human approval before saving credentials, placing orders, changing leverage, or closing positions.

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

Error
Location
scripts/cex_trader_cli.py:29
Finding

Exchange Credentials Can Be Transmitted to Arbitrary or Plaintext Endpoints

Content
View full analysis

Vulnerability Details

File Location: scripts/cex_trader_cli.py, lines 29 and 32–51; credential flow at lines 150–160
Vulnerability Type: Unrestricted destination and insecure transport for sensitive credentials
Risk Level: High

Vulnerable Code

python
MCP_SERVER_URL = os.environ.get("MCP_SERVER_URL", "http://localhost:3000")


def call_tool(tool_name: str, params: dict) -> dict:
    """Call an MCP tool via HTTP POST."""
    url = f"{MCP_SERVER_URL}/tools/{tool_name}"
    data = json.dumps(params).encode("utf-8")
    req = urllib.request.Request(
        url,
        data=data,
        headers={"Content-Type": "application/json"},
        method="POST",
    )
    try:
        with urllib.request.urlopen(req, timeout=30) as resp:
            return json.loads(resp.read().decode())
    except urllib.error.HTTPError as e:
        body = e.read().decode()
        print(f"HTTP Error {e.code}: {body}", file=sys.stderr)
        sys.exit(1)
    except urllib.error.URLError as e:
        print(f"Connection error: {e.reason}", file=sys.stderr)
        print(f"Is the MCP server running at {MCP_SERVER_URL}?", file=sys.stderr)
        sys.exit(1)
python
def cmd_setup_save(args):
    params = {
        "exchange": args.exchange,
        "apiKey": args.apiKey,
        "secretKey": args.secretKey,
    }
    if args.passphrase:
        params["passphrase"] = args.passphrase
    print_result(call_tool("cex-setup-save", params))

Technical Analysis

The CLI takes MCP_SERVER_URL directly from the environment and appends the selected tool path without validating the scheme or destination. It does not:

  • Require HTTPS for non-loopback destinations.
  • Restrict credential submission to an approved host.
  • Warn the user when credentials are sent to a custom destination.
  • Pin or otherwise constrain the expected server identity.

The setup save operation places the exchange API key, secret key, and optional OKX passphrase into a JSON request ...[truncated 1955 chars]

Remediation
View remediation

Remediation Suggestions

  1. Parse and validate MCP_SERVER_URL before constructing requests.
  2. Permit plaintext HTTP only when the resolved destination is a loopback address such as 127.0.0.1, ::1, or an explicitly validated localhost endpoint.
  3. Require HTTPS for every non-loopback destination.
  4. Use an allowlist containing the documented hosted MCP hostname by default.
  5. Require an explicit high-friction option, such as --allow-custom-server, before sending credentials to a custom host.
  6. Display the resolved scheme and destination and obtain confirmation immediately before transmitting credentials.
  7. Prevent redirects during credential submission, or revalidate the scheme and destination after every redirect.
  8. Consider avoiding central credential transmission entirely by signing exchange requests locally or using a local credential broker.
  9. Recommend exchange keys restricted to trading-only permissions, IP allowlists, and the minimum required exchange account scope.
  10. Add automated tests proving that credential submission is rejected for arbitrary HTTP hosts, user-info URLs, malformed URLs, and redirects to untrusted destinations.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/cex_trader_cli.py:195
Finding

Exchange Secrets Are Accepted Through Process Command-Line Arguments

Content
View full analysis

Vulnerability Details

File Location: scripts/cex_trader_cli.py, usage example at line 8 and parser definitions at lines 195–200
Vulnerability Type: Sensitive information exposure through command-line arguments
Risk Level: Medium

Vulnerable Code

python
Usage:
    python cex_trader_cli.py setup check
    python cex_trader_cli.py setup save --exchange binance --apiKey KEY --secretKey SECRET
python
s_save = setup_sub.add_parser("save", help="Save API credentials")
s_save.add_argument("--exchange", required=True, choices=["okx", "binance"])
s_save.add_argument("--apiKey", required=True, help="API Key")
s_save.add_argument("--secretKey", required=True, help="API Secret")
s_save.add_argument("--passphrase", help="Passphrase (required for OKX)")
s_save.set_defaults(func=cmd_setup_save)

Technical Analysis

The CLI requires users to supply exchange authentication material as ordinary command-line arguments. Depending on the operating system and execution environment, process arguments may be exposed through:

  • Process-listing and process-monitoring interfaces.
  • Shell history files.
  • Terminal session recording.
  • Job orchestration metadata.
  • Support bundles, audit logs, or endpoint telemetry.
  • Wrapper scripts and CI/CD logs.

Although process-list visibility varies by platform and configuration, shell-history persistence alone makes literal secret arguments an unsafe credential-entry mechanism. The embedded usage example encourages this behavior.

Attack Path

  1. A user follows the CLI syntax and supplies a live API secret:
    bash
    python scripts/cex_trader_cli.py setup save \
      --exchange binance \
      --apiKey LIVE_KEY \
      --secretKey LIVE_SECRET
    
  2. The command is retained in shell history or captured by local process-monitoring tooling.
  3. A local user, compromised process, administrator, backup reader, or telemetry operator obtains the recorded argument string.
  4. The recovered credentials are use ...[truncated 610 chars]
Remediation
View remediation

Remediation Suggestions

  1. Replace --secretKey and --passphrase with hidden interactive input using getpass.getpass().
  2. Prefer obtaining the API key through a protected environment variable, secret manager, or inherited file descriptor rather than a literal argument.
  3. If non-interactive operation is necessary, support reading secrets from files with strict permission checks or from standard input without echo.
  4. Remove literal-secret command examples from module documentation and user-facing instructions.
  5. Retain command-line secret arguments only as a deprecated compatibility path, emit a prominent warning, and remove them in a future release.
  6. Ensure errors never print submitted credential values.
  7. Document shell-history cleanup and immediate credential rotation for users who previously followed the exposed syntax.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (13)

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

Critical
Category
Data Flow
Confidence
95% confidence
Finding

The CLI builds the destination URL from the MCP_SERVER_URL environment variable and then sends requests to it, including highly sensitive parameters such as API keys and trading commands. Because the default scheme is plain HTTP and there is no allowlist or origin validation, a malicious or misconfigured environment can redirect requests to an attacker-controlled server, enabling credential exfiltration or unauthorized trade requests.

Content

Scanner excerpt · scripts/cex_trader_cli.py (reported line 43)May include surrounding context.

python
method="POST",
    )
    try:
        with urllib.request.urlopen(req, timeout=30) as resp:
            return json.loads(resp.read().decode())
    except urllib.error.HTTPError as e:
        body = e.read().decode()

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The skill advertises built-in risk controls, idempotency, rate limiting, setup flow, and a broader implementation surface than is evidenced here, while apparently acting mainly as a thin client to a remote MCP server. For a trading skill, this mismatch is dangerous because users or agents may rely on nonexistent safeguards when handling real funds, leverage, and API credentials.

Content

No source excerpt is available for this finding.

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding

Suspicious Unicode normalization or mixed-script content

Content

No source excerpt is available for this finding.

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding

Suspicious Unicode normalization or mixed-script content

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding

The skill declares network use to a hosted MCP endpoint and relies on environment-provided exchange credentials, but it does not define explicit tool scope or allowed-tools constraints. In an agent environment, missing scope boundaries can allow broader-than-expected invocation patterns and make credential-handling/network actions less auditable and easier to misuse.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The description includes broad trigger phrases like 'buy crypto', 'sell crypto', 'swap tokens', and similar generic trading language without clear activation constraints. In agent ecosystems, such vague triggers can cause accidental routing of ordinary conversation into high-risk trading actions, especially when the skill can place spot and leveraged futures orders.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The skill exposes setup tools that save and verify exchange API credentials, and while the metadata notes transmission to the MCP server, the user-facing tool description around setup is not sufficiently prominent about remote handling and persistence implications. This can mislead users into entering sensitive trading credentials without fully understanding where they are sent or how they are managed.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The example file demonstrates live futures trading actions including opening leveraged long/short positions, closing positions, and cancelling orders, but it provides no explicit user-facing warning that these operations can cause immediate financial loss or execute irreversible market actions. In an agent skill context, examples are often reused directly by developers or autonomous systems, so omission of safety guidance increases the risk of accidental real-money trades or misuse of high-risk leveraged functions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The example file demonstrates live order placement and cancellation against real exchanges without any warning that these actions can execute actual trades, incur losses, or require use of testnet/sandbox credentials. In an agent skill context, copy-pasteable examples strongly influence downstream usage, so omission of safety guidance increases the chance of accidental real-money transactions.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The spot and futures trading commands place live orders and the futures close command closes positions, which can directly affect user funds, yet the code provides no confirmation prompt or explicit warning at the point of execution. The brief parser help labels the commands, but it does not warn that these are real trading actions with financial consequences.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
82% confidence
Finding

Changing leverage is a safety-critical operation that can materially alter liquidation risk, but this function executes the request immediately with no confirmation prompt or warning. The parser help only describes the command mechanically and does not disclose the potential impact on account risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The setup save command collects apiKey and secretKey from CLI arguments and transmits them to the MCP server over whatever base URL is configured, which defaults to unsecured HTTP. In this trading-skill context, those credentials can grant direct account access and order execution, so interception or redirection of this request can lead to account takeover and financial loss.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
96% confidence
Finding

The README understates the available MCP tool surface, omitting order-query and market-data capabilities that are described elsewhere in the skill metadata. In a trading skill, inaccurate documentation of callable tools can mislead operators, reviewers, or agent policy layers about what actions are possible, weakening security review and increasing the chance that higher-risk capabilities are exposed without proper guardrails.

Content

No source excerpt is available for this finding.