Back to skill

Security audit

moss-trade-bot-factory-en

Security checks for vulnerabilities and agentic risk

Overview

The skill is coherent for crypto bot backtesting and optional simulated trading, but it needs Review because it persists trading credentials and can send authenticated platform requests with weak endpoint and credential-handling safeguards.

Install only if you are comfortable with a crypto trading automation skill that can persist platform credentials, upload strategy/backtest data, and run an automated simulated trading loop. Keep the platform URL on a trusted HTTPS origin, protect ~/.moss-trade-bot/agent_creds.json with owner-only permissions, avoid passing secrets on the command line, and review auto-trading and auto-resubmission behavior before enabling platform features.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (4)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/trading_client.py:38
Finding

Authenticated API traffic can be sent to an arbitrary non-HTTPS platform endpoint

Content
View full analysis

Vulnerability Details

File Location: scripts/trading_client.py:38-44, 66-99
Vulnerability Type: Insufficient URL validation and insecure transport of sensitive API data
Risk Level: High

Vulnerable Code

python
self.base_url = str(base_url or "").rstrip("/")
if not self.base_url:
    raise ValueError(
        "Platform base URL missing. Pass --platform-url explicitly or store "
        "base_url in agent_creds.json before using trading/verify features."
    )
parsed = urllib.parse.urlsplit(self.base_url)
if parsed.path not in ("", "/"):
    raise ValueError(
        "Platform base URL must be the site origin only, for example "
        "'https://ai.moss.site'. The client appends the API prefix "
        "automatically and will request "
        "'https://ai.moss.site/api/v1/moss/agent/agents/bind' "
        "for bind."
    )
python
def _request(self, method: str, path: str, body: dict = None,
             query: dict = None, need_auth: bool = True,
             custom_prefix: str = None) -> dict:
    prefix = custom_prefix if custom_prefix is not None else API_PREFIX
    full_path = f"{prefix}{path}"
    url = f"{self.base_url}{full_path}"

    canonical_query = ""
    if query:
        sorted_params = sorted(query.items())
        canonical_query = urllib.parse.urlencode(sorted_params)
        url = f"{url}?{canonical_query}"

    raw_body = ""
    if body is not None:
        raw_body = json.dumps(body, separators=(",", ":"))

    headers = dict(DEFAULT_HEADERS)

    if need_auth and self.api_key:
        ts, nonce, sig = self._sign(method, full_path, canonical_query, raw_body)
        headers["X-API-KEY"] = self.api_key
        headers["X-TS"] = ts
        headers["X-NONCE"] = nonce
        headers["X-SIGNATURE"] = sig
        if self.bot_id and path in ACCOUNT_BOUND_PATHS:
            headers["X-BOT-ID"] = self.bot_id

    req = urllib.
...[truncated 2937 chars]
Remediation
View remediation

Remediation Suggestions

  • Require parsed.scheme == "https" for all authenticated, binding, upload, and trading operations.
  • Reject URLs containing user information, fragments, unexpected query strings, or non-approved ports.
  • Prefer an explicit allowlist containing the declared platform hostname. If custom enterprise endpoints are required, place them behind a separate opt-in setting with a clear warning.
  • Disable automatic redirects for authenticated requests, or revalidate every redirect destination and prohibit cross-origin redirects.
  • Never forward API headers or request bodies to a redirected origin.
  • Validate TLS certificates using the system trust store and do not provide an option to disable certificate verification.
  • Consider binding credentials to the expected platform origin and reject a credential file whose stored origin differs from the requested origin.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/live_trade.py:84
Finding

Platform API secrets are stored without enforced restrictive file permissions

Content
View full analysis

Vulnerability Details

File Location: scripts/live_trade.py:84-92
Vulnerability Type: Insecure local storage of authentication credentials
Risk Level: Medium

Vulnerable Code

python
if "api_secret" in result and args.save:
    to_save = {
        "binding_id": result.get("binding_id", ""),
        "api_key": result["api_key"],
        "api_secret": result["api_secret"],
        "base_url": client.base_url,
    }
    with open(args.save, "w") as f:
        json.dump(to_save, f, indent=2)
    print(f"\nCredentials saved to {args.save} (bind only; create realtime bot with create-bot)", file=sys.stderr)

Technical Analysis

The credential file contains both the API key and API secret but is created with ordinary open(..., "w"). Its permissions therefore depend on the process umask. Under a permissive umask, the resulting file may be readable by other local users.

The implementation also does not verify that the destination is a regular file, reject symbolic links, create the parent directory with private permissions, or use an atomic replacement. These omissions can permit credential disclosure or unintended file replacement when the selected path or its parent directory is writable by another principal.

Persistent local storage is necessary for the declared upload and live-trading workflow, but unrestricted ambient file permissions are not necessary for that functionality and violate least-privilege credential handling.

Attack Path

  1. The user invokes live_trade.py bind with --save.
  2. The process creates the credential file using the current umask.
  3. The file receives group- or world-readable permissions in a permissive environment.
  4. Another local user reads the stored api_key, api_secret, binding_id, and platform URL.
  5. The local attacker constructs authenticated platform requests using the stolen credentials.

An alternative path is possible when an atta ...[truncated 559 chars]

Remediation
View remediation

Remediation Suggestions

  • Create the credential directory with mode 0700.
  • Create new credential files atomically with mode 0600, for example through os.open using O_CREAT | O_EXCL | O_WRONLY and a mode of 0o600.
  • Reject symbolic links using O_NOFOLLOW where supported and verify with fstat that the opened object is a regular file.
  • For updates, write to a private temporary file in the same directory, flush and synchronize it, then atomically replace the target.
  • Check existing credential-file permissions before use and refuse to proceed when group or world access is enabled.
  • Avoid printing credential contents and document the required ownership and permission model.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/live_trade.py:10
Finding

API secrets can be supplied through exposed command-line arguments

Content
View full analysis

Vulnerability Details

File Location: scripts/live_trade.py:10-25, 228-279
Vulnerability Type: Sensitive information exposure through process arguments and shell history
Risk Level: Medium

Vulnerable Code

python
# Check status:
python live_trade.py status --key ak_xxx --secret as_xxx

# Open long:
python live_trade.py open-long --key ak_xxx --secret as_xxx --amount 1000 --leverage 10

# Open short:
python live_trade.py open-short --key ak_xxx --secret as_xxx --amount 1000 --leverage 10

# Close position:
python live_trade.py close --key ak_xxx --secret as_xxx --side LONG

# Get price:
python live_trade.py price --key ak_xxx --secret as_xxx

# Order history:
python live_trade.py orders --key ak_xxx --secret as_xxx

# Trade history:
python live_trade.py trades --key ak_xxx --secret as_xxx
python
# status
p = sub.add_parser("status", help="Account + positions + price")
p.add_argument("--key", default="")
p.add_argument("--secret", default="")
p.add_argument("--creds", default="", help="Load from credentials JSON")

# price
p = sub.add_parser("price", help="Get mark price")
p.add_argument("--key", default="")
p.add_argument("--secret", default="")
p.add_argument("--creds", default="")

# open-long
p = sub.add_parser("open-long", help="Open long position")
p.add_argument("--key", default="")
p.add_argument("--secret", default="")
p.add_argument("--creds", default="")

# open-short
p = sub.add_parser("open-short", help="Open short position")
p.add_argument("--key", default="")
p.add_argument("--secret", default="")
p.add_argument("--creds", default="")

The same --secret interface is also registered for the close, orders, and trades subcommands through line 279.

Technical Analysis

Command-line arguments are commonly retained in shell history and may be visible through process inspection, debugging tools, job schedulers, terminal ...[truncated 1257 chars]

Remediation
View remediation

Remediation Suggestions

  • Remove the --secret command-line option and all examples that demonstrate it.
  • Require a permission-protected credential file for non-interactive use.
  • If interactive secret entry is necessary, use getpass.getpass() so the value is neither echoed nor placed in shell history.
  • Where available, integrate with an operating-system credential store or secret manager.
  • Ensure errors and diagnostic output never include parsed credentials or the complete command line.
  • Recommend rotation of any secret previously supplied through command-line arguments.

T08 · Insecure Dependencies

Warning
Location
scripts/requirements.txt:1
Finding

Dependency installation uses unpinned future releases without integrity hashes

Content
View full analysis

Vulnerability Details

File Location: scripts/requirements.txt:1-4; scripts/setup_env.py:19-21
Vulnerability Type: Non-reproducible and insufficiently verified dependency installation
Risk Level: Medium

Vulnerable Code

scripts/requirements.txt:

text
pandas>=2.0.0
numpy>=1.24.0
ccxt>=4.0.0
scipy>=1.11.0

scripts/setup_env.py:

python
subprocess.check_call([sys.executable, "-m", "venv", str(venv_dir)])
subprocess.check_call([str(python_bin), "-m", "pip", "install", "--upgrade", "pip"])
subprocess.check_call([str(python_bin), "-m", "pip", "install", "-r", str(requirements_path)])

Technical Analysis

Every dependency uses an open-ended lower bound. A setup performed later can therefore install any future version selected by pip, including versions that have not been audited with this Skill. Transitive dependencies are also unresolved and unpinned.

No package hashes are supplied, and the setup unconditionally upgrades pip before installing the project dependencies. This creates a mutable supply-chain surface and prevents deterministic reproduction of the reviewed environment.

No typosquatted or known-malicious package was identified in the supplied requirements. The vulnerability is the unsafe dependency resolution and integrity model rather than evidence that the currently named projects are malicious.

Attack Path

  1. The user approves local environment setup as instructed by the Skill.
  2. setup_env.py upgrades pip and installs dependencies from the configured package index.
  3. Pip resolves releases that satisfy the open-ended >= constraints at installation time.
  4. A compromised, malicious, or unexpectedly incompatible future package or transitive release is downloaded.
  5. Package build or installation logic executes in the user's context, and the installed code later executes when imported by the Skill.

Exploitation requires compromise ...[truncated 534 chars]

Remediation
View remediation

Remediation Suggestions

  • Pin every direct and transitive dependency to an exact reviewed version.
  • Generate a lock file for each supported Python version and platform.
  • Require package hashes with pip's --require-hashes mode.
  • Avoid automatically upgrading pip during normal Skill setup; pin and review the installer version separately when an upgrade is required.
  • Configure an explicit trusted package index or an internally controlled artifact repository.
  • Add automated vulnerability and provenance checks for locked artifacts.
  • Periodically update dependencies through a reviewed process rather than resolving unrestricted future releases during end-user installation.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (52)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description understates operational behaviors such as downloading market data from Binance and generating local fingerprint/intermediate files. When a skill's public description omits network retrieval and artifact generation, users and policy systems may grant trust without understanding the actual data flows and side effects, increasing the chance of unintended external access or handling of sensitive local data.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description understates operational behaviors such as downloading market data from Binance and generating local fingerprint/intermediate files. When a skill's public description omits network retrieval and artifact generation, users and policy systems may grant trust without understanding the actual data flows and side effects, increasing the chance of unintended external access or handling of sensitive local data.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

This script is explicitly designed to run a live trading bot and automatically opens and closes positions in a loop without any interactive confirmation, dry-run default, or prominent runtime warning. In the context of an agent skill that can be invoked from natural-language instructions, this increases the risk of unintended real-money trades from misconfiguration, user misunderstanding, or unsafe automation.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
94% confidence
Finding

The open_long, open_short, and close_position methods place market orders or close positions, which are safety-critical and potentially irreversible operations. These functions contain no confirmation step and no nearby user-facing warning about live trading impact or financial risk.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding

The skill invokes shell commands, reads and writes local files, and can access the network, but it declares no explicit tool scope or permission boundary. That creates a confused-deputy risk: an agent may execute powerful actions the user did not clearly authorize, including installing packages, writing to /tmp and home-directory credential paths, fetching remote data, and contacting an external platform.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The instructions require generating bilingual bot copy in Chinese and English for every run, and explicitly require producing the other language even when the user primarily used only one language. This imposes a language policy on users without offering a choice or explaining a necessary region-specific reason in the skill file.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This documentation gives detailed guidance for leveraged crypto trading, including leverage up to 150x, stop-loss sizing, and profit amplification via rolling, but it does not include an explicit warning about the substantial risk of rapid financial loss. In the context of a skill that creates and evolves trading bots, this omission can encourage unsafe deployment by making high-risk settings appear routine and endorsed.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
78% confidence
Finding

The skill directs persistent storage of long-lived platform credentials in a fixed location under the home directory, enabling reuse across sessions. If local permissions are weak, the host is shared, or the agent later performs unintended actions, these retained API credentials increase the blast radius and duration of compromise.

Content

Scanner excerpt · knowledge/platform_ops.md (reported line 29)May include surrounding context.

  1. Get the Pair Code: after login, the platform shows a pair code which the user copies
  2. Run bind:
    bash
    mkdir -p ~/.moss-trade-bot
    cd {baseDir}/scripts && "$PYTHON_BIN" live_trade.py bind \
      --platform-url "https://ai.moss.site" \
      --pair-code "<pair_code>" \
    

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

These lines state that upload metadata must include both zh and en fields and that the script rejects submissions if English is not provided. This is a natural-language locale constraint that forces specific languages rather than offering user choice, and the file does not justify it as a region-specific compliance requirement.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
91% confidence
Finding

The instruction to automatically analyze rejection details, modify results, redownload data, and resubmit without asking the user authorizes consequential external actions without renewed consent. In a trading/verification workflow, this can cause unintended submissions, repeated network actions, and silent alteration of user-provided artifacts, reducing user control and auditability.

Content

Scanner excerpt · knowledge/platform_ops.md (reported line 111)May include surrounding context.

md
### Verification result handling

- **verified** -> passed. The platform automatically creates an Agent; tell the user the `bot_id`
- **rejected** -> do not ask the user. Analyze `mismatch_details` yourself:
  - precision issue (difference <1%) -> replace with `verified_result` and resubmit
  - fingerprint mismatch -> redownload data and regenerate the fingerprint
  - large difference (>10%) -> tell the user the platform replay engine differs significantly

File System Enumeration

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code scans file system directories looking for sensitive files. This could be reconnaissance for credential theft.

Content

Scanner excerpt · knowledge/platform_ops.md (reported line 154)May include surrounding context.

Preflight checks

bash
ls -la ~/.moss-trade-bot/agent_creds.json 2>/dev/null || true
# If needed, confirm whether the platform URL is already saved in local creds:
python3 - <<'PY'
import json, pathlib

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This code presents its user-facing documentation and command-line help entirely in Chinese, including the module description and operational constraints. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation unless the locale restriction is explicitly justified, which it is not here.

Content

No source excerpt is available for this finding.

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Confidence
75% confidence
Finding

Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Content

Scanner excerpt · scripts/core/fetcher.py (reported line 95)May include surrounding context.

python
if use_cache and os.path.exists(cache_file):
        mod_time = os.path.getmtime(cache_file)
        if time.time() - mod_time < 86400:
            print(f"Using cached file: {os.path.basename(cache_file)}", file=__import__('sys').stderr)
            return pd.read_csv(cache_file, parse_dates=["timestamp"])

    if not since_date:

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Confidence
75% confidence
Finding

Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Content

Scanner excerpt · scripts/core/fetcher.py (reported line 106)May include surrounding context.

python
matches = sorted(glob.glob(pattern), key=os.path.getmtime, reverse=True)
            if matches:
                best = matches[0]
                print(f"Using cached file: {os.path.basename(best)}", file=__import__('sys').stderr)
                return pd.read_csv(best, parse_dates=["timestamp"])

    exchange = get_exchange(exchange_id)

Dynamic import via __import__()

Medium
Category
Dangerous Code Execution
Confidence
75% confidence
Finding

Dynamic import() can load arbitrary modules at runtime, bypassing static analysis and potentially importing malicious code.

Content

Scanner excerpt · scripts/core/fetcher.py (reported line 161)May include surrounding context.

python
# 缓存
    df.to_csv(cache_file, index=False)
    print(f"Fetched {len(df)} candles for {symbol} {timeframe}, cached to {cache_file}", file=__import__('sys').stderr)

    return df

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The script requires a credentials JSON file and accesses api_key and api_secret to initialize the trading client. While this is functionally necessary, there is no warning in code comments, docstrings, or startup output that sensitive credentials are being loaded and used for network-authenticated trading operations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script saves API credentials, including the secret, to a user-specified JSON file in plaintext and does not enforce restrictive file permissions or clearly warn the user about the sensitivity of the material. In the context of a trading bot, compromise of these credentials could let an attacker query account state and place or close trades, making the issue materially security-relevant.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The create-bot flow requires zh and en fields for display name, persona, and description, and the CLI marks all corresponding Chinese and English arguments as required. This imposes a language/locale constraint rather than offering user choice or documenting a justified region-specific requirement.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The command-line interface requires both Chinese and English variants for bot display name, persona, and description. This is a natural-language policy concern because the tool forces specific locales instead of allowing user opt-in or alternative language choices.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This JSON schema uses Chinese natural-language descriptions and constraint text throughout, but provides no indication that the skill is China-specific or that users can opt into this locale. Under the policy, forcing a specific language without user choice or documented justification is a natural-language policy violation.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/setup_env.py (reported line 19)May include surrounding context.

python
requirements_path = scripts_dir / "requirements.txt"
    python_bin = venv_dir / ("Scripts/python.exe" if os.name == "nt" else "bin/python")

    subprocess.check_call([sys.executable, "-m", "venv", str(venv_dir)])
    subprocess.check_call([str(python_bin), "-m", "pip", "install", "--upgrade", "pip"])
    subprocess.check_call([str(python_bin), "-m", "pip", "install", "-r", str(requirements_path)])

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/setup_env.py (reported line 20)May include surrounding context.

python
python_bin = venv_dir / ("Scripts/python.exe" if os.name == "nt" else "bin/python")

    subprocess.check_call([sys.executable, "-m", "venv", str(venv_dir)])
    subprocess.check_call([str(python_bin), "-m", "pip", "install", "--upgrade", "pip"])
    subprocess.check_call([str(python_bin), "-m", "pip", "install", "-r", str(requirements_path)])

    print(f"Local virtualenv ready: {venv_dir}")

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/setup_env.py (reported line 21)May include surrounding context.

python
subprocess.check_call([sys.executable, "-m", "venv", str(venv_dir)])
    subprocess.check_call([str(python_bin), "-m", "pip", "install", "--upgrade", "pip"])
    subprocess.check_call([str(python_bin), "-m", "pip", "install", "-r", str(requirements_path)])

    print(f"Local virtualenv ready: {venv_dir}")
    print(f"Use this Python for bundled scripts: {python_bin}")

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The validator requires both zh and en fields and rejects zh without Chinese characters and en containing any Chinese characters. This hard-codes a specific locale policy in the skill logic, and the file does not indicate user choice or a documented region-specific justification for enforcing only this bilingual format.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This code performs HTTP requests that may include HMAC authentication headers, account identifiers, and trading payloads, but the request path has no print/log statement, confirmation prompt, or explicit user-facing disclosure at the point of transmission. Although the module docstring describes configuration, it does not warn users that account/trading data and auth material will be sent over the network.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.