Back to skill

Security audit

Crypto Listing Alert

Security checks for vulnerabilities and agentic risk

Overview

The skill broadly matches its stated subscription-alert purpose, but it handles reusable API and bot credentials in ways users should review carefully before installing.

Install only if you trust listingalert.org and are comfortable giving its backend your email or chat identifiers and, for Telegram/Discord delivery, full bot tokens. Prefer a dedicated bot token with minimal permissions, avoid custom API URLs unless you control them, do not use HTTP endpoints, and rotate any API key or bot token that may have been exposed in command history or logs.

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)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
index.cjs:218
Finding
Reusable Bot Credentials Are Retrieved from Local Configuration and Disclosed to the Remote Backend<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:99-106, 191-197, 236-242`; `index.cjs:218-260, 307-349` **Vulnerability Type**: Excessive credential access and remote credential disclosure **Risk Level**: High ### Evidence `SKILL.md:99-106`: ```markdown - Telegram channel needs `telegram_chat_id` + `bot_token` - Discord channel needs `discord_channel_id` + `bot_token` 5. Credential sources (must follow): - `telegram.chatId`: parse from current message body/context metadata. - `telegram.botToken`: read from openclaw config file. - `discord.botToken`: read from openclaw config file. - `discord.channelId`: read from openclaw config file. - `email`: prefer current logged-in account email; if user provides another valid email, use user input. - If any required value is missing, tell user to fix config/source first. ``` `index.cjs:218-260`: ```js const telegramBotToken = getArgValue(args, "--bot-token"); const discordBotToken = getArgValue(args, "--bot-token"); const billingCycle = getArgValue(args, "--billing") || "monthly"; if (!plan || !exchanges) { outputError(args, "Missing required flags: --plan, --exchanges"); process.exit(1); } if (channel !== "telegram" && channel !== "discord" && channel !== "email") { outputError(args, "Invalid --channel. Use telegram, discord or email"); process.exit(1); } if ((channel === "telegram" || channel === "discord") && !telegramBotToken) { outputError(args, "Missing required flag: --bot-token"); process.exit(1); } if (channel === "telegram" && !telegramChatID) { outputError(args, "Missing required flag for telegram channel: --telegram"); process.exit(1); } if (channel === "discord" && !discordChannelID) { outputError(args, "Missing required flag for discord channel: --discord-channel"); process.exit(1); } if (channel === "email" && !email) { outputError(args, "Missing required flag for email channel: --email"); process.exit(1); } if (channel === "email" && !isValidE ...[truncated 2614 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not instruct the agent to read reusable bot tokens from general OpenClaw configuration. 2. Replace complete bot-token transfer with OAuth or a narrowly scoped, revocable integration credential. 3. Prefer a local relay architecture: keep the platform token on the user's machine and have the backend return signed notification events for local delivery. 4. If remote custody is unavoidable, require explicit informed consent immediately before transmission and identify the exact recipient, purpose, retention period, and revocation procedure. 5. Encrypt credentials at rest using a managed secrets service and strictly limit backend access. 6. Prevent credentials from appearing in API responses, application logs, telemetry, exception messages, and support diagnostics. 7. Rotate existing tokens that may already have been transmitted, and provide users with a one-step integration revocation procedure. 8. Separate credentials by service and destination so compromise of one alert integration cannot affect unrelated channels or servers. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
index.cjs:149
Finding
Unrestricted Custom API URL Permits Credential Exfiltration and Plaintext Transmission<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:144-147`; `index.cjs:149-157, 601-635` **Vulnerability Type**: Unvalidated remote endpoint and insecure transport **Risk Level**: High ### Evidence `SKILL.md:144-147`: ```markdown Optional custom server: ```bash node skills/crypto-listing-alert/index.cjs login --api-key <API_KEY> --api-url <URL> --json ``` ``` `index.cjs:149-157`: ```js function handleLogin(args) { const apiKey = getArgValue(args, "--api-key"); const apiURL = getArgValue(args, "--api-url") || DEFAULT_API_URL; if (!apiKey) { process.stderr.write("Error: --api-key is required\n"); process.exit(1); } const cfg = { api_url: apiURL, api_key: apiKey }; ``` `index.cjs:601-635`: ```js function apiRequest(cfg, method, urlPath, body) { return new Promise((resolve, reject) => { // Ensure api_url ends with / for proper URL joining let baseUrl = cfg.api_url; if (!baseUrl.endsWith("/")) { baseUrl += "/"; } const fullURL = new URL(urlPath.replace(/^\//, ""), baseUrl); const mod = fullURL.protocol === "https:" ? https : http; const jsonData = body ? JSON.stringify(body) : null; const options = { method, hostname: fullURL.hostname, port: fullURL.port, path: fullURL.pathname + fullURL.search, headers: { "Content-Type": "application/json", }, timeout: 15000, }; if (cfg.api_key) { options.headers["X-API-Key"] = cfg.api_key; } if (jsonData) { options.headers["Content-Length"] = Buffer.byteLength(jsonData); } const req = mod.request(options, (res) => { ``` ### Technical Analysis The login command accepts an arbitrary `--api-url` and persists it without validating its scheme, hostname, or port. The request helper selects HTTPS only when the URL protocol is exactly `https:` and otherwise uses the Node.js HTTP module. Consequently, an `http://` endpoint is supported and receives the API key without ...[truncated 1887 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the custom production endpoint option unless it is strictly necessary. 2. Enforce `https:` and reject HTTP and all unsupported URL schemes before saving configuration. 3. Restrict hosts to `listingalert.org` or a small explicit allowlist of trusted production domains. 4. Reject embedded usernames or passwords, unexpected ports, malformed URLs, loopback addresses, link-local addresses, and private-network destinations unless a separate development mode explicitly permits them. 5. Keep any development endpoint override behind an environment-specific build or clearly marked unsafe option that never carries production credentials. 6. Revalidate the saved endpoint before every authenticated request so direct configuration-file tampering cannot bypass login-time checks. 7. Use normal TLS certificate and hostname validation, and consider certificate or public-key pinning where operationally feasible. 8. Bind API keys to an intended audience or server identity so a credential captured by another endpoint cannot be reused. 9. Display a high-severity confirmation warning before changing endpoints and never silently migrate existing credentials to a new host. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
index.cjs:149
Finding
API Keys and Bot Tokens Are Exposed Through Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:140, 191-197, 236-242`; `index.cjs:149, 218-219, 307-308` **Vulnerability Type**: Sensitive information exposure through process arguments and command history **Risk Level**: Medium ### Evidence `SKILL.md:140`: ```bash node skills/crypto-listing-alert/index.cjs login --api-key <API_KEY> --json ``` `SKILL.md:191-197`: ```bash node skills/crypto-listing-alert/index.cjs pay --plan <PLAN_CODE> --exchanges <EXCHANGE_CSV> --billing <monthly|yearly> --channel telegram --telegram <CHAT_ID> --bot-token <TOKEN> --json ``` ```bash node skills/crypto-listing-alert/index.cjs pay --plan <PLAN_CODE> --exchanges <EXCHANGE_CSV> --billing <monthly|yearly> --channel discord --discord-channel <CHANNEL_ID> --bot-token <TOKEN> --json ``` `index.cjs:149`: ```js const apiKey = getArgValue(args, "--api-key"); ``` `index.cjs:218-219`: ```js const telegramBotToken = getArgValue(args, "--bot-token"); const discordBotToken = getArgValue(args, "--bot-token"); ``` ### Technical Analysis The documented and implemented interface requires reusable secrets to be passed as command-line arguments. Process arguments are not an appropriate secret-transport mechanism because they can be captured by shell history, command execution records, agent tool logs, telemetry, debugging output, crash reports, or process-inspection facilities available to other local principals. The local configuration file is created with mode `0600`, which appropriately restricts the saved API key at rest, but that protection does not prevent exposure before the secret is written. The same issue applies every time a bot token is supplied to `pay` or `subscribe`. ### Attack Path 1. The user or agent follows the documented login, payment, or subscription command. 2. The API key or bot token is inserted directly into the command line. 3. The shell, agent runtime, orchestration layer, or telemetry system records the command. 4. Alternatively, another lo ...[truncated 855 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `--api-key` and `--bot-token` as normal secret-input mechanisms. 2. Read secrets from protected standard input without terminal echo, or retrieve them from an operating-system credential store. 3. Where automation is required, accept a credential reference or file descriptor rather than the secret value itself. 4. Ensure temporary secret files, if unavoidable, are created atomically with mode `0600`, are never placed in shared directories, and are deleted immediately after use. 5. Configure agent execution and telemetry systems to redact known secret fields and prevent complete command capture. 6. Avoid environment variables for long-lived secrets where process environments can be inspected or logged. 7. Add credential-pattern redaction to errors, diagnostic output, and support bundles. 8. Rotate API keys and bot tokens that may already have appeared in command history or execution logs. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (7)

Hidden Instructions

High
Category
Prompt Injection
Content
---
name: crypto-listing-alert
description: Use when users want to subscribe, pay, or manage Crypto Listing Alert notifications for exchange listing events and need Telegram, Discord, or Email delivery with API-key login.
version: 1.0.2
Confidence
60% confidence
Finding
Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Credential Access

High
Category
Privilege Escalation
Content
```

- If `logged_in = true`: proceed normally.
- If `logged_in = false`: immediately guide user to get API key from website first, then login:

  1. Visit `https://listingalert.org`
  2. Register/login and generate API key
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
The skill explicitly instructs the agent to read Telegram/Discord bot tokens and channel identifiers from local OpenClaw config, which expands its access to sensitive local secrets beyond what a subscription-management workflow minimally requires. If followed, this creates a secret-exfiltration and privilege-abuse path because the agent may retrieve credentials from the host environment and send them to the external CLI/backend during payment or subscription operations.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The skill says to pull data from message context and local config but does not clearly disclose that sensitive identifiers and tokens may be accessed and transmitted as part of the workflow. This lack of transparency increases the risk of unauthorized data use because users and operators are not properly warned that local secrets and contextual metadata are inputs to external actions.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The login flow saves the provided API key to a file in the user's home directory and only reports 'Login successful. API key saved.' It does not clearly disclose that a credential is being persisted on disk at a specific path, which is a sensitive operation involving credential storage.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The code sends email addresses, Telegram chat IDs, Discord channel IDs, and bot tokens to the remote API as part of subscription creation. Although the command purpose implies remote interaction, there is no explicit warning in the code's user-facing text that these potentially sensitive values are transmitted to the service.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The payment flow posts email addresses, chat or channel identifiers, and bot tokens to the API endpoint to create an order. This is a network transmission of potentially sensitive data, but the user-facing help and runtime messages do not explicitly disclose that these values will be sent to the external service.

Static analysis

No suspicious patterns detected.