Back to skill

Security audit

Crypto Wave Scanner

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to be a real crypto scanner, but it needs review because it loads live third-party JavaScript for a trading dashboard and exposes its local server more broadly than advertised.

Review before installing or running. The skill does not request Binance credentials or place trades, but its dashboard may influence trading decisions while loading live JavaScript from a CDN, and its server listens beyond localhost by default. Prefer running it only on a trusted network, treat signals as informational, and consider fixing the server bind and bundling or integrity-pinning the chart library.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T03 · Remote Payload Retrieval and Execution

Warning
Location
assets/wave-scanner.html:6
Finding
Remote JavaScript Dependency Loaded Without Integrity Verification<![CDATA[ ## Vulnerability Details **File Location**: `assets/wave-scanner.html:6` **Vulnerability Type**: Remote executable dependency without Subresource Integrity protection **Risk Level**: Medium ### Vulnerable Code ```html <script src="https://unpkg.com/lightweight-charts@4.1.3/dist/lightweight-charts.standalone.production.js"></script> ``` ### Technical Analysis The dashboard loads and executes JavaScript directly from the third-party `unpkg.com` CDN at runtime. Although the dependency version is pinned to `4.1.3`, the page does not specify a Subresource Integrity (`integrity`) hash and does not bundle a reviewed local copy. Consequently, the code that ultimately executes is not fully represented by the audited project. If the CDN, package publication process, hosted artifact, or delivery path is compromised, modified JavaScript could be returned and executed automatically when the dashboard opens. The remote script executes in the browser under the dashboard's HTTP origin. The application also lacks a restrictive Content Security Policy, increasing the freedom available to compromised dependency code. ### Attack Path 1. An attacker compromises the CDN response, upstream package artifact, or package publishing account. 2. The user launches `scripts/serve.py` and opens the dashboard. 3. The browser requests the script from `https://unpkg.com`. 4. Because no integrity hash is present, the browser accepts a modified response. 5. The attacker-controlled JavaScript executes in the dashboard's browser context. 6. The script can manipulate displayed prices and trading signals, issue arbitrary network requests permitted by the browser, and access any non-HttpOnly data subsequently stored under the same dashboard origin. ### Impact Assessment The immediate privilege obtained is JavaScript execution in the user's browser under the dashboard origin, not operating-system-level code execution. A malicious dependency could falsify financial indicators, alte ...[truncated 504 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Download and review the required Lightweight Charts release, then serve it as a local static asset: ```html <script src="./vendor/lightweight-charts-4.1.3.min.js"></script> ``` 2. If remote hosting is unavoidable, calculate and pin the exact cryptographic digest: ```html <script src="https://unpkg.com/lightweight-charts@4.1.3/dist/lightweight-charts.standalone.production.js" integrity="sha384-REPLACE_WITH_VERIFIED_DIGEST" crossorigin="anonymous"></script> ``` The digest must be generated from a separately verified copy of the exact artifact. 3. Add a restrictive Content Security Policy. After moving inline JavaScript into a local file, an appropriate baseline would be: ```html <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; connect-src https://fapi.binance.com; style-src 'self'; img-src 'self' data:; object-src 'none'; base-uri 'none'; frame-ancestors 'none'"> ``` 4. Pin and verify dependency artifacts during development or packaging rather than retrieving executable code dynamically at runtime. 5. Document the dependency version and checksum so future upgrades require an explicit review and checksum update. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/serve.py:22
Finding
Local Dashboard Server Listens on All Network Interfaces<![CDATA[ ## Vulnerability Details **File Location**: `scripts/serve.py:22` **Vulnerability Type**: Unnecessary network exposure caused by an unrestricted bind address **Risk Level**: Low ### Vulnerable Code ```python print(f"🌊 Cedars Wave Scanner running at http://localhost:{PORT}/wave-scanner.html") print("Press Ctrl+C to stop.") with socketserver.TCPServer(("", PORT), Handler) as httpd: httpd.serve_forever() ``` ### Technical Analysis Passing an empty host string to `socketserver.TCPServer` causes the server to listen on all available network interfaces rather than only on the loopback interface. This behavior contradicts the program's presentation as a local server and the printed `localhost` URL. The current document root is the project's `assets` directory, so the confirmed exposure is limited to static files in that directory. Nevertheless, binding to all interfaces unnecessarily expands the attack surface and violates least-privilege networking principles. The handler also provides no authentication or client-address restriction. Any host capable of reaching port 7890 can request content exposed by the static server. ### Attack Path 1. A user starts `scripts/serve.py` on a machine connected to a shared or otherwise reachable network. 2. The server binds port 7890 on every available interface. 3. A remote host discovers or directly connects to the machine's port 7890. 4. The remote host requests `/wave-scanner.html` or other files available beneath the served assets directory. 5. The server returns those files without authentication. ### Impact Assessment A reachable remote party can access static content served from the assets directory. No authentication bypass, operating-system privilege escalation, arbitrary file write, or confirmed access outside the static document root was identified. The present confidentiality impact is low because the audited assets are not sensitive. However, the exposure could disclose future files added to ...[truncated 191 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Bind the server explicitly to IPv4 loopback: ```python HOST = "127.0.0.1" with socketserver.TCPServer((HOST, PORT), Handler) as httpd: httpd.serve_forever() ``` 2. Use the same host constant for the displayed URL and browser launch so the documented and actual behavior cannot diverge: ```python HOST = "127.0.0.1" URL = f"http://{HOST}:{PORT}/wave-scanner.html" ``` 3. Keep the assets directory limited to public static resources and do not place configuration files, tokens, logs, or other sensitive data beneath the document root. 4. If remote access is intentionally introduced later, require explicit configuration rather than making it the default. Add authentication, transport security, access controls, and appropriate firewall restrictions before exposing the service. 5. Consider setting `allow_reuse_address` through a dedicated server subclass for operational reliability, while retaining the explicit loopback binding. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (12)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The declared description describes a full market-scanning and analysis tool with technical computations, real-time data access, and terminal scanning. The supplied code chunk only launches a local static file server and opens a browser to a dashboard page. While serving the dashboard could be a supporting component of the overall skill, this chunk by itself does not implement the core declared behavior and instead performs only local hosting/browser-launch functionality. That is a material mismatch between the described primary capability and the actual code behavior in this chunk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The code substantially matches the CLI scanning portion of the description in that it evaluates Binance futures symbols using EMA9/21/50, RSI, volume confirmation, 1h trend, and MACD, scores each symbol out of 6, and prints entry/TP/stop guidance. However, the declared description prominently claims a visual live browser dashboard with charts and overlays, plus real-time scanning across 10 coins. None of that visual or live dashboard functionality exists in this code chunk; it is a one-shot terminal script only. Additionally, the default symbol list contains 8 coins rather than 10, and the scanner targets the Binance Futures testnet URL. The description also suggests both entry and exit wave detection, but the implemented logic is clearly oriented toward bullish setup scoring rather than explicit exit/exhaustion detection. These are material description-to-behavior mismatches.

Ae1

High
Category
analysis-evasion
Content
- `assets/wave-scanner.html` — self-contained browser dashboard (TradingView Lightweight Charts)
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill advertises executable shell-based workflows (`python3 scripts/serve.py`, `python3 scripts/wave_scanner.py`) but does not declare any tool scope such as allowed tools or permissions. That creates an execution-boundary problem: a host or user may run code without explicit authorization metadata, reducing transparency and making review and sandboxing harder.

Description-Behavior Mismatch

Medium
Confidence
98% confidence
Finding
The manifest says the scanner scores each coin using a distinct '1h trend', implying analysis on a 1-hour timeframe. Here the code computes the supposed 1h trend from the same current klines array and even comments that the caller should pass 1h data, but refresh() only fetches one selected interval per symbol, so the displayed score does not match the described behavior.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The comment and variable names document this logic as a 1h trend calculation, yet the implementation derives it from the same closes array and refresh() passes only one dataset from the user-selected interval. This is an active contradiction between the code's inline documentation and how the code actually behaves.

Context-Inappropriate Capability

Medium
Confidence
92% confidence
Finding
The skill's stated purpose is a crypto market scanner using Binance public API, which justifies network access but not spawning an OS-level executable. Invoking curl.exe adds a subprocess execution capability that is broader than needed for scanning and is context-inappropriate for this kind of analytics tool.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
SYMBOLS = ["BTCUSDT", "ETHUSDT", "SOLUSDT", "XRPUSDT", "BNBUSDT", "AVAXUSDT", "LINKUSDT", "DOGEUSDT"]

def curl_get(path):
    r = subprocess.run(["curl.exe", "-s", BASE + path], capture_output=True)
    return json.loads(r.stdout.decode("utf-8"))

def ema(data, period):
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Missing User Warnings

Low
Confidence
85% confidence
Finding
This HTML/JavaScript code fetches data from Binance Futures over the network, but the only disclosure is an inline code comment at L155, which is not user-facing. Under the code-file criteria, network calls that transmit user or system data should have some visible disclosure, logging, or documentation; here the page auto-starts fetching on load without a user warning.

Description-Behavior Mismatch

Low
Confidence
95% confidence
Finding
The module docstring says the script is used as `python3 wave_scanner.py [--alert] [--symbols BTC ETH SOL]`, implying alerting behavior is part of the tool. However, the argument parser only implements --symbols and --min-score, so the documented behavior does not match the actual code.

Intent-Code Divergence

Low
Confidence
97% confidence
Finding
This is an active documentation contradiction: the docstring explicitly tells users they can pass --alert, but argparse never defines that flag. That makes the inline usage guidance inaccurate rather than merely incomplete.

Missing User Warnings

Low
Confidence
88% confidence
Finding
The code performs an external HTTP request by invoking curl against the Binance Futures testnet, but this action is not disclosed through a comment, docstring detail, or user-facing message near the operation. For a code file, outbound network activity should have some visible disclosure unless it is clearly warned elsewhere; the top-level docstring says it scans Binance Futures but does not explicitly warn that live network requests will be made.