Back to skill

Security audit

Apex Crypto Intelligence

Security checks for vulnerabilities and agentic risk

Overview

This crypto-analysis skill is mostly purpose-aligned, but it makes misleading safety claims and uses network and exchange credentials more broadly than users may expect.

Review carefully before installing. Use only dedicated read-only exchange keys, never keys with trading or withdrawal permissions, avoid putting wallet addresses, secrets, private strategies, or personal data in prompts, and treat the verification mode as making live outbound market-data requests.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (3)

T09 · Insecure Skill Coding Practices

Warning
Location
client.py:217
Finding

Unsanitized user queries are disclosed to a third-party analysis service

Content
View full analysis
dict: """ Build the exact payload sent to api.neurodoc.app. WHAT IS SENT: prices, volumes, query text WHAT IS NOT SENT: API keys, secrets, credentials, wallet addresses Run `python client.py` to print this payload and verify yourself. """ # Build context from LOCALLY-fetched data (only numbers, no keys) context_lines = [f"Market query: {query}", "", "LIVE MARKET DATA:"] for coin in market_data: if isinstance(coin, dict): context_lines.append( f" {coin.get('symbol','?').upper()}: " f"${coin.get('current_price',0):,.2f} " f"24h:{coin.get('price_change_percentage_24h',0):+.1f}% " f"MCap:${coin.get('market_cap',0)/1e9:.1f}B" ) context_lines.append("\nEXCHANGE DATA:") for ex in exchange_data: if ex: context_lines.append( f" {ex.get('exchange','?')}: " f"bid={ex.get('bid',0)} ask={ex.get('ask',0)} " f"vol={ex.get('volume',0)}" ) flow_code = f'''flow CryptoAnalysis {{ using target "neuroaether" version ">=0.3"; input text query; node Apex: crypto mode="{mode}", language="en"; output text result from Apex; }}''' payload = { "code": flow_code, "query": "\n".join(context_lines), } return payload ``` The resulting payload is transmitted without further validation: ```python # Step 3: Build payload — VERIFY: no keys in this dict payload = build_api_requ ...[truncated 2948 chars]
Remediation
View remediation
str: if not isinstance(query, str): raise TypeError("Query must be a string") query = query.strip() if not query: raise ValueError("Query must not be empty") if len(query) > MAX_QUERY_LENGTH: raise ValueError(f"Query exceeds {MAX_QUERY_LENGTH} characters") return query ``` 2. Add detection and redaction for common credential patterns, authorization headers, private keys, seed phrases, email addresses, and wallet addresses. Because automated redaction is imperfect, do not claim that personal data can never be sent. 3. Display an explicit notice or obtain consent before forwarding free-form text to NeuroDoc, particularly when the Skill is embedded in another application. 4. Prefer structured inputs such as asset symbols and predefined analysis options over unrestricted natural-language context whenever possible. 5. Add tests proving that: - Oversized queries are rejected. - Known secret formats are blocked or redacted. - Only approved payload fields are transmitted. - Environment credentials cannot appear in serialized requests. 6. Update `SKILL.md` to accurately explain that the full user query is transmitted and may contain sensitive information unless the user removes it. Do not state that all queries are sanitized until corresponding controls exist. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
client.py:217
Finding

Unrestricted mode value permits injection into remotely executed Aetherlang code

Content
View full analysis
dict: """ Build the exact payload sent to api.neurodoc.app. WHAT IS SENT: prices, volumes, query text WHAT IS NOT SENT: API keys, secrets, credentials, wallet addresses Run `python client.py` to print this payload and verify yourself. """ # Build context from LOCALLY-fetched data (only numbers, no keys) context_lines = [f"Market query: {query}", "", "LIVE MARKET DATA:"] for coin in market_data: if isinstance(coin, dict): context_lines.append( f" {coin.get('symbol','?').upper()}: " f"${coin.get('current_price',0):,.2f} " f"24h:{coin.get('price_change_percentage_24h',0):+.1f}% " f"MCap:${coin.get('market_cap',0)/1e9:.1f}B" ) context_lines.append("\nEXCHANGE DATA:") for ex in exchange_data: if ex: context_lines.append( f" {ex.get('exchange','?')}: " f"bid={ex.get('bid',0)} ask={ex.get('ask',0)} " f"vol={ex.get('volume',0)}" ) flow_code = f'''flow CryptoAnalysis {{ using target "neuroaether" version ">=0.3"; input text query; node Apex: crypto mode="{mode}", language="en"; output text result from Apex; }}''' ``` ### Technical Analysis The `mode` argument is interpolated directly into executable Aetherlang DSL source inside a quoted attribute. There is no allowlist, escaping, grammar validation, or structured serialization. A value containing a quotation mark and DSL syntax can terminate the intended `mode` string and modify the program sent to the remote execution endpoint. For example, a c ...[truncated 2052 chars]
Remediation
View remediation
str: if mode not in ALLOWED_MODES: raise ValueError(f"Unsupported mode: {mode!r}") return mode ``` 2. Do not attempt to secure arbitrary DSL fragments solely by escaping quotation marks. An allowlist is appropriate because the documented feature set contains only a small number of modes. 3. Prefer a structured API in which mode is transmitted as a distinct JSON enum and the server generates the DSL internally. 4. Require the server to independently validate: - Permitted targets and versions. - Permitted node types and attributes. - Maximum node and statement counts. - Authentication, authorization, and request quotas. 5. Add tests using quotation marks, newlines, semicolons, braces, comments, and known Aetherlang control tokens to verify that all non-allowlisted values are rejected before network transmission. ]]>

T05 · Unauthorized Access and Privilege Escalation

Note
Location
client.py:68
Finding

Exchange API keys are unnecessarily attached to public market-data requests

Content
View full analysis
dict: """ Fetch from Binance. Uses API key for higher rate limits if available. Key is sent ONLY to api.binance.com, never to neurodoc. """ api_key, _ = get_exchange_keys("BINANCE") headers = {} if api_key: headers["X-MBX-APIKEY"] = api_key # Sent to Binance ONLY url = f"https://api.binance.com/api/v3/ticker/24hr?symbol={symbol}" ``` Bybit: ```python api_key, api_secret = get_exchange_keys("BYBIT") headers = {} if api_key and api_secret: ts = str(int(time.time() * 1000)) sign_str = f"{ts}{api_key}5000" signature = hmac.new(api_secret.encode(), sign_str.encode(), hashlib.sha256).hexdigest() headers = { "X-BAPI-API-KEY": api_key, # Sent to Bybit ONLY "X-BAPI-TIMESTAMP": ts, "X-BAPI-SIGN": signature, } url = f"https://api.bybit.com/v5/market/tickers?category=spot&symbol={symbol}" ``` KuCoin: ```python api_key, api_secret = get_exchange_keys("KUCOIN") headers = {} if api_key and api_secret: ts = str(int(time.time() * 1000)) path = f"/api/v1/market/orderbook/level1?symbol={symbol}" sign_str = f"{ts}GET{path}" signature = hmac.new(api_secret.encode(), sign_str.encode(), hashlib.sha256).hexdigest() headers = { "KC-API-KEY": api_key, # Sent to KuCoin ONLY "KC-API-TIMESTAMP": ts, "KC-API-SIGN": signature, } url = f"https://api.kucoin.com/api/v1/market/orderbook/level1?symbol={symbol}" ``` MEXC: ```python api_key, _ = get_exchange_keys("MEXC") headers = {} ...[truncated 3501 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (13)

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The verification path explicitly claims that 'nothing is transmitted' and 'No data was sent to any server,' but it performs live HTTP requests to CoinGecko and multiple exchanges. This is security-relevant because users may run verification mode under the false assumption that it is offline/safe, causing unintended outbound connections and disclosure of their IP, behavior, and exchange-authenticated requests.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill declares access to environment variables and uses external networking, but it does not declare an explicit permission/tool scope to constrain or communicate those capabilities. In a BYOK crypto context, undeclared env and network access is risky because the skill handles exchange credentials and sends data to a third-party API, reducing transparency and increasing the chance of over-broad execution in hosts that rely on manifest scoping.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
86% confidence
Finding

The skill is explicitly designed to transmit user queries and aggregated market data to an external service, which is a real data-exposure boundary. Even though the document claims API keys are excluded, users may still send sensitive trading intent, strategies, or other confidential text in queries, and the safety claim is only documentation unless enforced by code and policy.

Content

Scanner excerpt · SKILL.md (reported line 44)May include surrounding context.

md
metadata:
  skill_type: api_connector
  external_endpoints:
    - https://api.neurodoc.app/aetherlang/execute
  operator_note: "api.neurodoc.app operated by NeuroDoc Pro (same as masterswarm.net), Hetzner DE"
  privacy_policy: https://masterswarm.net
  key_safety: "Exchange keys used locally only — never transmitted to api.neurodoc.app. Keys are read from env vars per-request and excluded from all API payloads."

External Transmission

Medium
Category
Data Exfiltration
Confidence
84% confidence
Finding

The API example shows direct POST requests to a third-party endpoint, confirming that skill output depends on external transmission. In this trading-analysis context, that can expose user prompts, watchlists, and potentially sensitive market hypotheses or operational metadata to a remote operator, which is a meaningful privacy and confidentiality risk.

Content

Scanner excerpt · SKILL.md (reported line 149)May include surrounding context.

1. Live Market Data + Cross-Exchange Scanner

text
POST https://api.neurodoc.app/aetherlang/execute
Content-Type: application/json
json

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · client.py (reported line 28)May include surrounding context.

python
from typing import Optional
from urllib.parse import urlencode

NEURODOC_API = "https://api.neurodoc.app/aetherlang/execute"


# ═══════════════════════════════════════════════════════════════

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · client.py (reported line 55)May include surrounding context.

python
async def fetch_coingecko(coin_ids: list[str]) -> list[dict]:
    """Free tier — no API key needed"""
    url = "https://api.coingecko.com/api/v3/coins/markets"
    params = {
        "vs_currency": "usd",
        "ids": ",".join(coin_ids),

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · client.py (reported line 78)May include surrounding context.

python
if api_key:
        headers["X-MBX-APIKEY"] = api_key  # Sent to Binance ONLY
    
    url = f"https://api.binance.com/api/v3/ticker/24hr?symbol={symbol}"
    async with httpx.AsyncClient() as client:
        r = await client.get(url, headers=headers, timeout=10)
        if r.status_code == 200:

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · client.py (reported line 109)May include surrounding context.

python
"X-BAPI-SIGN": signature,
        }
    
    url = f"https://api.bybit.com/v5/market/tickers?category=spot&symbol={symbol}"
    async with httpx.AsyncClient() as client:
        r = await client.get(url, headers=headers, timeout=10)
        if r.status_code == 200:

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · client.py (reported line 143)May include surrounding context.

python
"KC-API-SIGN": signature,
        }
    
    url = f"https://api.kucoin.com/api/v1/market/orderbook/level1?symbol={symbol}"
    async with httpx.AsyncClient() as client:
        r = await client.get(url, headers=headers, timeout=10)
        if r.status_code == 200:

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · client.py (reported line 166)May include surrounding context.

python
if api_key:
        headers["X-MEXC-APIKEY"] = api_key   # Sent to MEXC ONLY
    
    url = f"https://api.mexc.com/api/v3/ticker/24hr?symbol={symbol}"
    async with httpx.AsyncClient() as client:
        r = await client.get(url, headers=headers, timeout=10)
        if r.status_code == 200:

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · client.py (reported line 197)May include surrounding context.

python
"SIGN": signature,
        }
    
    url = f"https://api.gateio.ws/api/v4/spot/tickers?currency_pair={symbol}"
    async with httpx.AsyncClient() as client:
        r = await client.get(url, headers=headers, timeout=10)
        if r.status_code == 200:

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Line L252 sets language="en" in the generated flow, which forces a specific language regardless of user preference. This is a natural-language policy issue because the file does not offer an opt-in, fallback, or explanation that the skill is intentionally English-only.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The markdown includes multiple example payloads that set language="en" explicitly in the skill invocation. Because these examples present English as the default invocation pattern without asking the user to choose a language, they can steer usage toward a fixed locale despite the file later noting Greek support.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.