Back to skill

Security audit

Cryptowatch

Security checks for vulnerabilities and agentic risk

Overview

The reviewed local code is a coherent cryptocurrency price CLI, but the install instructions tell users to run an unpinned remote npm package that does not clearly match the reviewed package identity.

Review before installing. The local scripts appear limited to CoinGecko price queries and local alert-rule storage, but do not run the documented npx command unless it is pinned to a reviewed version and the npm package identity is verified against these artifacts. Expect network calls to CoinGecko and manual, not continuous, alert checks.

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

T08 · Insecure Dependencies

Warning
Location
SKILL.md:39
Finding
Unpinned Third-Party Package Is Downloaded and Executed via npx<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:39-43`; duplicated in `README.md:25-29` **Vulnerability Type**: Unpinned remote package execution and supply-chain risk **Risk Level**: Medium ### Complete Code Snippets `SKILL.md:39-43`: ```markdown ## Installation ```bash npx @gztanht/cryptowatch ``` ``` `README.md:25-29`: ```markdown ## 🚀 Quick Start ```bash # Install npx @gztanht/cryptowatch ``` The local manifest identifies the reviewed project differently at `package.json:1-4`: ```json { "name": "cryptowatch", "version": "1.0.2", "description": "₿ CryptoWatch - 加密货币价格监控,24h 涨跌幅排行榜", ``` ### Technical Analysis The documented `npx @gztanht/cryptowatch` command can retrieve the current package release from the npm registry and execute its package entry point with the invoking user's privileges. The command does not pin an exact version or provide an integrity value, so the code executed by a future installation can differ from the source reviewed in this audit. In addition, the reviewed manifest names the local package `cryptowatch`, whereas the command executes `@gztanht/cryptowatch`. The repository contents therefore do not establish that the registry artifact invoked by the documentation is identical to the audited code. This is a supply-chain execution boundary rather than evidence that the current repository contains a malicious payload. Exploitation requires the referenced npm package, its publisher account, or its publication process to become malicious or compromised. ### Attack Path 1. An attacker compromises the npm publisher account, publication token, build pipeline, or another component controlling `@gztanht/cryptowatch`. 2. The attacker publishes a malicious version and makes it the version selected by the unpinned `npx` command. 3. A user follows the installation instructions and runs `npx @gztanht/cryptowatch`. 4. npm downloads the remotely ...[truncated 924 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin the documented command to an exact, reviewed package version, for example: ```bash npx --yes @gztanht/cryptowatch@1.0.2 ``` 2. Ensure that the npm package identity matches the identity declared by the reviewed source, or clearly document and verify why the registry package uses a different scoped name. 3. Publish npm provenance attestations and retain a reproducible mapping between source commits, release tags, and registry artifacts. 4. Use a lockfile with exact dependency resolution for development and packaged releases. 5. Document a safer installation workflow that separates downloading or installing the package from executing it, allowing users to inspect the resolved package first. 6. Protect npm publication credentials with multi-factor authentication, short-lived automation tokens, restricted token permissions, and a controlled release pipeline. 7. Update both `SKILL.md` and `README.md` so that all installation examples use the same pinned and verifiable release. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • 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
Findings (26)

Ae1

High
Category
analysis-evasion
Content
node scripts/watch.mjs btc
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/watch.mjs btc
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/watch.mjs btc
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/alert.mjs btc --above 100000
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/alert.mjs btc --above 100000
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/alert.mjs btc --above 100000
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Rp1

Medium
Category
MCP Rug Pull
Confidence
93% confidence
Finding
The README instructs users to run `npx @gztanht/cryptowatch` without pinning a specific version. This makes execution dependent on whatever package version is currently published, creating a supply-chain risk where a compromised or malicious update could be fetched and executed immediately by users.

Lp3

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding
The skill advertises network-dependent functionality via CoinGecko and Node/NPM usage, but it does not declare an explicit tool scope such as allowed network access. Missing scope metadata weakens the trust boundary for an agent platform because reviewers and runtime policy engines cannot clearly determine what external capabilities the skill is expected to use.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The manifest description and the main usage/documentation content are presented in Chinese, and the file does not indicate that users may choose another language. This can violate a language/locale policy when a skill implicitly forces one language for all users without opt-in or justification.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding
Using 'npx @gztanht/cryptowatch' without pinning a version causes the latest published package to be fetched and executed at runtime. This creates a supply-chain risk: if the package is updated maliciously, compromised, or a breaking version is released, users may execute unreviewed code with network and local environment access.

Natural-Language Policy Violations

Medium
Confidence
98% confidence
Finding
The script presents its description, help, errors, and status messages entirely in Chinese, which forces a specific language experience. The policy only permits this when the skill offers language choice or clearly documents and justifies the locale restriction, which is not present here.

Description-Behavior Mismatch

Medium
Confidence
97% confidence
Finding
The manifest describes '实时监控' and '价格突破自动预警', implying continuous monitoring with automatic alerting. In reality, the code merely saves alert definitions to a local JSON file and only checks prices when the script is explicitly run; it even states that checks must be run manually or via cron.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This code presents its title, help text, status messages, and errors in Chinese, which imposes a specific language on all users. The policy allows locale constraints only when justified or when users can opt in, neither of which is present here.

Intent-Code Divergence

Medium
Confidence
94% confidence
Finding
The top-of-file documentation states '实时价格监控' (real-time price monitoring), which implies ongoing observation. In practice, the script makes a single API request, prints output, and terminates, so the documentation overstates what the code does.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
This file contains natural-language descriptions, help output, and runtime messages in Chinese only, including the header and command help. Under the policy, forcing a specific language without user opt-in is a locale/language policy violation unless the skill is clearly documented as region-specific, which is not evident here.

External Transmission

Medium
Category
Data Exfiltration
Content
import fetch from 'node-fetch';

const API = 'https://api.coingecko.com/api/v3';

// 配置
const DEFAULT_COINS = ['bitcoin', 'ethereum', 'solana', 'bnb', 'xrp', 'dogecoin', 'cardano', 'avalanche-2'];
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
import fetch from 'node-fetch';

const API = 'https://api.coingecko.com/api/v3';

// 配置
const DEFAULT_COINS = ['bitcoin', 'ethereum', 'solana', 'bnb', 'xrp', 'dogecoin', 'cardano', 'avalanche-2'];
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
import fetch from 'node-fetch';

const API = 'https://api.coingecko.com/api/v3';

// 配置
const DEFAULT_COINS = ['bitcoin', 'ethereum', 'solana', 'bnb', 'xrp', 'dogecoin', 'cardano', 'avalanche-2'];
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
import fetch from 'node-fetch';

const API = 'https://api.coingecko.com/api/v3';

// 配置
const DEFAULT_COINS = ['bitcoin', 'ethereum', 'solana', 'bnb', 'xrp', 'dogecoin', 'cardano', 'avalanche-2'];
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
import fetch from 'node-fetch';

const API = 'https://api.coingecko.com/api/v3';

// 配置
const DEFAULT_COINS = ['bitcoin', 'ethereum', 'solana', 'bnb', 'xrp', 'dogecoin', 'cardano', 'avalanche-2'];
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Description-Behavior Mismatch

Medium
Confidence
98% confidence
Finding
The manifest describes '实时监控加密货币价格,价格突破自动预警' (real-time monitoring with automatic alerts on threshold breaks). However, the implementation is a CLI that fetches current prices or market rankings once per invocation and exits; there is no continuous monitoring loop, no threshold configuration, and no alerting behavior.

Missing User Warnings

Low
Confidence
84% confidence
Finding
This markdown file documents that the skill fetches live cryptocurrency data from the CoinGecko API, but it does not warn users that running the skill will make outbound network requests. For markdown files, SQP-2 applies when the skill description omits warnings about behaviors that could affect privacy or system integrity; even if low risk, external network access should be disclosed.

Natural-Language Policy Violations

Low
Confidence
88% confidence
Finding
The natural-language description is written in Chinese only, which can impose a language expectation on users without any opt-in or alternative locale indicated. Under the stated policy, forcing a specific language without user choice is a natural-language policy concern.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"author": "@gztanht",
  "license": "MIT",
  "dependencies": {
    "node-fetch": "^3.3.2"
  },
  "repository": {
    "type": "git",
Confidence
92% confidence
Finding
The dependency is specified with a caret range (^3.3.2), which allows future compatible releases to be installed implicitly. This weakens supply-chain predictability and can cause the skill to pick up vulnerable or malicious dependency updates without explicit review, especially because the package performs network-related functionality.

Unverifiable Dependency: node-fetch has 3 known advisory(ies) (CVE-2022-0235 (node-fetch forwards secure headers to untrusted sites); CVE-2022-2596 (node-fetch Inefficient Regular Expression Complexity ); CVE-2020-15168 (The `size` option isn't honored after following a redirect in node-fetch)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
87% confidence
Finding
The manifest references node-fetch without exact pinning, while known advisories exist for some node-fetch releases. Because the installed version is not fully constrained here, consumers may resolve to an affected release or remain unable to verify whether the dependency is safe, creating avoidable supply-chain and network-request risk.

Static analysis

No suspicious patterns detected.