Back to skill

Security audit

Neuro Scalp

Security checks for vulnerabilities and agentic risk

Overview

This disclosed crypto trading bot needs Review because it can place live OKX orders while testnet mode, risk controls, Redis access, and dashboard security are not safely scoped.

Do not install this with real OKX credentials or funded accounts as written. Treat it as research/prototype code until live trading is explicitly gated, testnet mode is enforced, Redis and the dashboard are private/authenticated, risk limits are actually applied, dependencies are updated, and model checkpoints come only from trusted verified sources. If testing, use isolated paper/testnet credentials with withdrawals disabled and strict exchange-side limits.

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

T05 · Unauthorized Access and Privilege Escalation

Error
Location
docker-compose.yml:3
Finding
Unauthenticated Redis Exposure Enables Forged Market Data and Unauthorized Trade Influence<![CDATA[ ## Vulnerability Details **File Location**: `docker-compose.yml:3-6`; related trust boundary at `main.py:50-89` **Vulnerability Type**: Unauthenticated service exposure and trusted-message injection **Risk Level**: High ### Vulnerable Code ```yaml redis: image: redis:alpine ports: - "6379:6379" ``` Redis messages are consumed without producer authentication or data-origin verification: ```python # Subscribe to the data feed channel channel = f"tick_{self.symbol.replace('/', '')}" await self.pub_sub.subscribe(channel) async for message in self.pub_sub.listen(): if not self.running: break if message['type'] == 'message': try: # 1. Parse Tick data = json.loads(message['data']) # 2. Update Features self.feature_engine.update(data) ob_snapshot = { 'bid': data['bid'], 'ask': data['ask'], 'bid_vol': data['bid_vol'], 'ask_vol': data['ask_vol'] } features = self.feature_engine.get_features(ob_snapshot) if len(self.feature_engine.prices) < self.feature_engine.window_size: continue signal_strength = self.agent.predict(features) if abs(signal_strength) > 0.5: await self.exec_engine.execute_signal( signal=signal_strength, price=data['last_price'] ) ``` ### Technical Analysis Docker publishes Redis port 6379 on the host without configuring authentication, ACLs, or transport encryption. Unless restricted by an external firewall, Docker's port publication makes the service reachable through host network interfaces. The strategy process treats messages received from the Redis channel as authentic exchange market data. It performs no producer authentication, message signing, freshness enforcement, schema constraints, numeric range validation, or comparison against an independent exchange p ...[truncated 1503 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the host port publication if Redis is only used between containers: ```yaml redis: image: redis:alpine expose: - "6379" ``` 2. Place Redis and application containers on a dedicated internal Docker network. 3. Configure Redis ACLs with separate, least-privileged users for publishers, consumers, and the dashboard. 4. Use TLS for any Redis connection that crosses a host or network trust boundary. 5. Require authenticated or cryptographically signed market-data messages. 6. Validate every tick with a strict schema: - Require finite numeric values. - Reject negative prices or volumes. - Require `bid <= ask`. - Enforce timestamp freshness and monotonicity. - Bound price deviation against a direct exchange data source. 7. Do not permit Redis-originated prices to flow directly into order placement without an independent exchange-price sanity check. 8. Add rate limiting, duplicate detection, and circuit breakers for abnormal message frequency. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
core/engine/execution.py:2
Finding
Configured Testnet and Financial Risk Controls Are Not Enforced in the Live Execution Path<![CDATA[ ## Vulnerability Details **File Location**: `core/engine/execution.py:2-51`; related configuration at `config/settings.yaml:1-16` **Vulnerability Type**: Fail-open live trading and ineffective risk controls **Risk Level**: High ### Vulnerable Code The configuration claims that testnet and several risk limits are enabled: ```yaml exchange: name: "okx" testnet: true # ⚠️ API 密钥请使用环境变量设置 # OKX_API_KEY, OKX_SECRET, OKX_PASSPHRASE api_key: "${OKX_API_KEY}" api_secret: "${OKX_SECRET}" passphrase: "${OKX_PASSPHRASE}" pairs: ["BTC-USDT-SWAP", "ETH-USDT-SWAP"] leverage: 10 risk: max_drawdown_daily: 0.03 # 3% max_position_size_usd: 10000 stop_loss_pct: 0.002 # 0.2% daily_kill_switch: true ``` The execution engine does not consume or enforce those settings: ```python class ExecutionEngine: def __init__(self, api_key, secret, password): self.exchange = ccxt.okx({ 'apiKey': api_key, 'secret': secret, 'password': password, 'enableRateLimit': True, 'options': {'defaultType': 'swap'} }) self.current_position = 0 self.daily_pnl = 0 async def execute_signal(self, signal, price): """ Signal: -1.0 to 1.0 """ if abs(signal) < 0.2: return # Weak signal filter # RISK CHECK if not self.check_risk(signal): return side = 'buy' if signal > 0 else 'sell' size = self.calculate_kelly_size(signal) try: # Post-only limit order to save fees (Scalping requirement) order = await self.exchange.create_order( symbol="BTC/USDT:USDT", type='limit', side=side, amount=size, price=price, params={'postOnly': True} ) logger.info(f"Order Placed: {side} {size} @ {price}") return order except Exception as e: ...[truncated 2433 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pass a validated environment mode into `ExecutionEngine`. 2. Enable CCXT sandbox mode before any API operation when testnet is configured, and verify that the selected endpoint is the expected test environment. 3. Fail closed at startup if: - The environment mode is missing or ambiguous. - Required credentials are missing. - Sandbox verification fails. - Risk limits are absent or invalid. 4. Require a separate explicit opt-in, such as `LIVE_TRADING_ENABLED=true`, before production orders are permitted. 5. Reconcile balances, positions, leverage, and open orders directly from OKX before each order decision. 6. Enforce configured maximum notional exposure, order size, order frequency, daily drawdown, and stop loss. 7. Track realized and unrealized PnL from authoritative exchange data rather than an unmodified local variable. 8. Add idempotency or signal-cooldown controls to prevent repeated orders from consecutive ticks. 9. Cancel stale orders and define a fail-safe response for network, exchange, and reconciliation failures. 10. Test the complete risk path with integration tests that verify no production endpoint is used in testnet mode. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
models/agent.py:26
Finding
PyTorch Checkpoint Loading Permits Unsafe Pickle-Compatible Deserialization<![CDATA[ ## Vulnerability Details **File Location**: `models/agent.py:26-29` **Vulnerability Type**: Unsafe model deserialization **Risk Level**: High ### Vulnerable Code ```python class AI_Trader: def __init__(self, model_path=None): self.model = ScalpingActorCritic(input_dim=3, action_dim=1) if model_path: self.model.load_state_dict(torch.load(model_path)) self.optimizer = torch.optim.Adam(self.model.parameters(), lr=1e-4) ``` The production entry point supplies a fixed checkpoint path: ```python self.agent = AI_Trader(model_path="models/checkpoints/latest.pth") ``` ### Technical Analysis The project pins PyTorch 2.1.0 and invokes `torch.load(model_path)` without a restricted weights-only mode. PyTorch checkpoint loading uses pickle-compatible deserialization, which is unsafe for untrusted files because crafted serialized objects can invoke attacker-selected Python behavior during loading. Calling `load_state_dict()` after `torch.load()` does not make the operation safe: deserialization has already occurred by the time state-dictionary validation begins. The checkpoint is local rather than remotely downloaded by the reviewed project, so exploitation requires an attacker or compromised deployment process to replace, introduce, or influence the checkpoint file. ### Attack Path 1. An attacker gains write access to `models/checkpoints/latest.pth`, compromises a distributed project artifact, or convinces an operator to install an untrusted checkpoint. 2. The attacker constructs a malicious pickle-compatible PyTorch checkpoint with a deserialization gadget. 3. The operator launches `main.py` or another path that initializes `AI_Trader` with that file. 4. `torch.load()` deserializes the crafted object before `load_state_dict()` validates model weights. 5. Attacker-controlled code executes with the privileges and environment of the trading process. ### Impact Assessment Successful exploitation provides arbitrary cod ...[truncated 418 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Prefer a non-executable model format such as Safetensors. 2. Upgrade to a supported PyTorch release and load only tensor weights using a restricted mode where available: ```python state_dict = torch.load( model_path, map_location="cpu", weights_only=True, ) self.model.load_state_dict(state_dict) ``` 3. Accept checkpoints only from a trusted build or training pipeline. 4. Verify every checkpoint against an expected cryptographic hash or digital signature before loading. 5. Make the checkpoint directory read-only to the runtime process. 6. Do not load model files supplied through user input or writable shared volumes. 7. Run model loading and inference under a dedicated, least-privileged account without unnecessary filesystem or administrative access. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
dashboard/app.py:18
Finding
Public Dashboard WebSocket Exposes Trading Telemetry Without Authentication<![CDATA[ ## Vulnerability Details **File Location**: `dashboard/app.py:18-48`; deployment exposure at `docker-compose.yml:17-21` **Vulnerability Type**: Missing authentication and WebSocket origin validation **Risk Level**: Medium ### Vulnerable Code ```python @app.get("/", response_class=HTMLResponse) async def get_dashboard(request: Request): return templates.TemplateResponse("index.html", {"request": request}) @app.websocket("/ws/metrics") async def websocket_endpoint(websocket: WebSocket): await websocket.accept() logger.info("New Dashboard Connection") # Subscribe to Redis channels pubsub = r.pubsub() await pubsub.subscribe("trade_events", "system_metrics", "tick_BTCUSDT-SWAP") try: async for message in pubsub.listen(): if message['type'] == 'message': # Forward Redis message directly to Frontend channel = message['channel'].decode('utf-8') data = json.loads(message['data']) payload = { "type": channel, "data": data } await websocket.send_json(payload) except Exception as e: logger.error(f"WebSocket Error: {e}") finally: await websocket.close() ``` The service is bound publicly by the supplied deployment configuration: ```yaml dashboard: build: . command: uvicorn dashboard.app:app --host 0.0.0.0 --port 8000 ports: - "8000:8000" ``` ### Technical Analysis The HTTP dashboard and WebSocket endpoint have no authentication or authorization checks. The WebSocket is accepted immediately, without validating a session, bearer token, API key, or the request's `Origin` header. Each connection creates a Redis pub/sub subscription and receives trade events, system metrics, and tick data. No connection quota or rate limit is applied. Public exposure through `0.0.0.0:8000` therefore makes operational telemetry available to any reachable client. ...[truncated 856 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require authenticated sessions or short-lived signed tokens before accepting the WebSocket. 2. Authorize users specifically for access to trading telemetry. 3. Validate the WebSocket `Origin` header against an explicit allowlist. 4. Bind the dashboard to localhost by default or place it behind an authenticated TLS reverse proxy. 5. Apply per-user and per-IP connection limits and rate limits. 6. Set idle timeouts and maximum connection lifetimes. 7. Reuse or carefully close Redis pub/sub resources for disconnected clients. 8. Limit exposed event fields to the minimum required by dashboard users. 9. Add security headers and audit logging for successful and failed access attempts. ]]>

T08 · Insecure Dependencies

Warning
Location
dashboard/templates/index.html:5
Finding
Dashboard Executes Third-Party CDN Scripts Without Integrity Verification<![CDATA[ ## Vulnerability Details **File Location**: `dashboard/templates/index.html:5-6` **Vulnerability Type**: Unverified third-party frontend dependency loading **Risk Level**: Medium ### Vulnerable Code ```html <script src="https://cdn.plot.ly/plotly-2.24.1.min.js"></script> <script src="https://cdn.tailwindcss.com"></script> ``` ### Technical Analysis The dashboard loads executable JavaScript from third-party CDN origins at page-render time. Neither script includes a Subresource Integrity hash. The Tailwind CDN URL is also not pinned to an immutable version. If a CDN account, upstream distribution system, DNS path, or mutable asset is compromised, altered JavaScript executes in the dashboard's browser origin. HTTPS protects transport against ordinary interception but does not protect against malicious or compromised upstream content. No restrictive Content Security Policy is shown that would reduce the consequences of injected script. ### Attack Path 1. A third-party CDN asset or its publishing pipeline is compromised, or a mutable asset is replaced upstream. 2. An operator opens the dashboard. 3. The browser downloads the altered JavaScript because the page contains no integrity hash. 4. The browser executes the script in the dashboard origin. 5. The injected code can read displayed telemetry, manipulate the dashboard, initiate network requests allowed by the browser, and access origin-scoped data available to the page. ### Impact Assessment Successful supply-chain compromise can execute arbitrary JavaScript in every dashboard user's browser. The immediate scope includes dashboard telemetry and any browser-accessible credentials or session data later added to the same origin. The reviewed implementation does not place OKX API credentials in the browser, so direct theft of those credentials is not established by the available code. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions 1. Self-host audited, pinned builds of Plotly and Tailwind. 2. If CDN delivery is retained, use immutable versioned URLs and valid Subresource Integrity hashes: ```html <script src="https://trusted-cdn.example/library-version.min.js" integrity="sha384-EXPECTED_HASH" crossorigin="anonymous"></script> ``` 3. Avoid Tailwind's runtime CDN script in production; compile a pinned Tailwind version into static CSS during the build. 4. Deploy a restrictive Content Security Policy that permits scripts only from required sources and avoids `unsafe-inline` where practical. 5. Pin frontend dependencies in a lockfile and include them in dependency-update and vulnerability-monitoring processes. 6. Review and update Plotly because the referenced version is old, while regression-testing dashboard behavior after upgrades. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (21)

Known Vulnerable Dependency: torch==2.1.0 — 16 advisory(ies): CVE-2025-2953 (PyTorch susceptible to local Denial of Service); CVE-2025-32434 (PyTorch: `torch.load` with `weights_only=True` leads to remote code execution); CVE-2024-31580 (PyTorch heap buffer overflow vulnerability) +13 more

Critical
Category
Supply Chain
Confidence
98% confidence
Finding
The requirement pins PyTorch to version 2.1.0, which the supplied finding indicates is affected by multiple published advisories, including severe memory safety issues and unsafe deserialization/RCE conditions. In an agent skill context, ML frameworks are often used to load model artifacts or process untrusted inputs, which makes a vulnerable torch version especially dangerous because exploitation could lead to code execution or denial of service in the host environment.

Missing User Warnings

High
Confidence
97% confidence
Finding
The README directs creation of a fully automated 24/7 live-trading system without prominently warning users about the possibility of rapid financial loss, model error, exchange failure, or unattended execution risk. In the context of autonomous trading, the absence of an upfront warning can normalize unsafe deployment and increase the chance that a user runs real-money strategies without understanding the operational and financial hazards.

Missing User Warnings

High
Confidence
98% confidence
Finding
The README explicitly targets perpetual futures and later mentions dynamic leverage adjustment, but does not clearly warn about leverage, liquidation, funding, and derivatives-specific risks. That omission is especially dangerous because leveraged perpetual products can amplify losses very quickly, and an autonomous system may increase exposure faster than a human operator can intervene.

Context-Inappropriate Capability

High
Confidence
97% confidence
Finding
The strategy loop autonomously converts model output into market actions by calling execute_signal whenever a threshold is met. Because this happens continuously on incoming Redis messages with no human approval, kill-switch check, risk-limit check, or anomaly validation shown here, malformed data, model failure, or misuse can trigger unwanted live trades at machine speed.

Missing User Warnings

High
Confidence
95% confidence
Finding
Automated trade execution occurs with no user-facing warning, confirmation, or visible consent mechanism in the file. In a system that can act on exchange credentials, this omission materially increases the chance of unauthorized or accidental financial activity, especially if the component is reused in a broader agent environment.

Known Vulnerable Dependency: fastapi==0.104.0 — 1 advisory(ies): CVE-2024-24762 (FastAPI is a web framework for building APIs with Python 3.8+ based on standard )

High
Category
Supply Chain
Confidence
90% confidence
Finding
The dependency is pinned to FastAPI 0.104.0, which the finding maps to a known advisory. Because FastAPI is an internet-facing web framework, known flaws can often be reached remotely through HTTP request handling, making the issue more dangerous in a service-oriented skill than a purely local utility.

Possible Typosquatting: 'uvicorn' resembles popular package 'gunicorn'

High
Category
Supply Chain
Confidence
70% confidence
Finding
Package name closely resembles a popular package, suggesting possible typosquatting. Attackers publish malicious packages with similar names to trick developers into installing them.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
The title and core description are presented entirely in Chinese, and the file does not indicate that language selection is optional or that the skill is region-specific. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The code places a live order on a real exchange directly from a trading signal with no user confirmation, simulation guard, environment separation, or explicit dry-run mode. In an automated trading skill, this is dangerous because any bad signal, misconfiguration, compromised upstream component, or accidental invocation can immediately trigger real financial transactions and losses.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The WebSocket endpoint accepts any client and forwards Redis pub/sub messages directly to them with no authentication, authorization, origin checks, or filtering. In this monitoring context, those channels may contain sensitive operational or trading data, so any party able to reach the endpoint can passively observe internal events in real time.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
The page creates a WebSocket using plain `ws://`, which provides no transport encryption or integrity protection. If this dashboard is accessed over an untrusted network, an attacker on-path can observe or tamper with live trading metrics and event data, potentially misleading operators or exposing sensitive operational information.

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
The code pulls live exchange credentials from environment variables and immediately initializes an execution engine capable of placing real orders. In this file's context, the program is an autonomous trading orchestrator with no safety gate, sandbox mode, permission prompt, or explicit restriction to paper trading, so compromise or accidental deployment could directly affect a funded account.

Insecure deserialization: torch.load() without weights_only=True

Medium
Category
Dangerous Code Execution
Content
def __init__(self, model_path=None):
        self.model = ScalpingActorCritic(input_dim=3, action_dim=1)
        if model_path:
            self.model.load_state_dict(torch.load(model_path))
        self.optimizer = torch.optim.Adam(self.model.parameters(), lr=1e-4)
    
    def predict(self, features):
Confidence
98% confidence
Finding
This is a true vulnerability because `torch.load(model_path)` uses Python pickle-based deserialization, which can execute attacker-controlled code during loading if the model file is untrusted or tampered with. In this trading-agent context, model paths may be externally supplied or updated from files, making unsafe model loading especially risky because compromise could lead to arbitrary code execution in the environment running the trader.

Natural-Language Policy Violations

Low
Confidence
94% confidence
Finding
The file includes operational guidance only in Chinese in the comments about how to provide API credentials. This is a natural-language locale policy issue because it imposes a single language without offering a choice or indicating that the skill is intentionally region-specific.

Missing User Warnings

Low
Confidence
76% confidence
Finding
The constructor receives API key, secret, and password and immediately uses them to initialize the exchange client. This accesses sensitive credentials, but the file provides no docstring, comment, or user-facing disclosure about credential use or the risks of supplying live trading secrets.

Intent-Code Divergence

Low
Confidence
91% confidence
Finding
The comment at L57 says the test data is saved to CSV so the backtester can pick it up, but immediately afterward the code sets `bt.df = test_data` at L63 to avoid that file-based path. This is an active contradiction between the inline documentation and the actual execution path, not merely omitted detail.

Missing User Warnings

Low
Confidence
88% confidence
Finding
The code exports out-of-sample test data to a CSV file, which is a file write affecting local user/system data. Although there are internal comments and logger messages elsewhere, there is no user-facing print, confirmation, or explicit warning at the point where this temporary file is created.

Missing User Warnings

Low
Confidence
86% confidence
Finding
The training simulation persists model weights to a checkpoint path using torch.save, which is a file write operation. The docstring explains the function purpose, but it does not warn the user that files will be created on disk or where they will be stored.

Intent-Code Divergence

Low
Confidence
97% confidence
Finding
The docstring at L17-L21 states that get_features generates only Order Book Imbalance and Microprice. However, the implementation also computes volatility at L34-L35 and returns it as the third element at L37, so the documentation contradicts the actual output.

Natural-Language Policy Violations

Low
Confidence
71% confidence
Finding
The comment explicitly treats Windows as unsupported for full signal handling and silently falls back with 'pass # Windows', which communicates a platform-specific constraint without any user choice or clear runtime disclosure. This is a natural-language policy concern because the file embeds a fixed platform limitation rather than surfacing it as an explicit opt-in or documented requirement.

Natural-Language Policy Violations

Low
Confidence
87% confidence
Finding
This manifest contains user-facing natural-language labels and descriptions only in Chinese, such as plan names, features, and comments, with no indication that the skill is intended exclusively for a Chinese-speaking audience. Under the language/locale policy, forcing a single language without user opt-in or documented justification can be a policy issue.

Static analysis

No suspicious patterns detected.