Back to skill

Security audit

Dexscan Skill

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches DexScan market-data use, but it needs review because its script searches parent folders for .env credentials and may use keys not intended for it.

Install only if you are comfortable sending token, wallet, and tweet queries to DexScan with your DexScan API credentials. Keep the skill isolated from repositories or parent folders that contain .env files, or require the publisher to change credential loading so it reads only explicit environment variables or a fixed skill-local file.

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

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/dexscan.js:20
Finding

Overly Broad Parent-Directory Credential Discovery

Content
View full analysis

Vulnerability Details

File Location: scripts/dexscan.js, lines 20–44
Vulnerability Type: Least-privilege violation through unrestricted ancestor .env discovery
Risk Level: Medium

Vulnerable Code

javascript
function readEnvFile() {
    const envConfig = {};
    let currentDir = __dirname;

    // Search upward for a .env file until reaching the filesystem root
    while (true) {
        const envPath = path.join(currentDir, '.env');
        if (fs.existsSync(envPath)) {
            const content = fs.readFileSync(envPath, 'utf-8');
            content.split('\n').forEach(line => {
                const match = line.match(/^\s*DS_ACCESS_KEY\s*=\s*"?([^"]*)"?/);
                if (match) envConfig.DS_ACCESS_KEY = match[1].trim();
                const match2 = line.match(/^\s*DS_SECRET_KEY\s*=\s*"?([^"]*)"?/);
                if (match2) envConfig.DS_SECRET_KEY = match2[1].trim();
            });
            break;
        }

        const parentDir = path.dirname(currentDir);
        // Stop after reaching the filesystem root
        if (parentDir === currentDir) {
            break;
        }
        currentDir = parentDir;
    }

    return envConfig;
}

Technical Analysis

The readEnvFile() function begins at the script directory and traverses every ancestor directory until it reaches the filesystem root. It reads the first .env file encountered and extracts DS_ACCESS_KEY and DS_SECRET_KEY.

This behavior is broader than the declared requirement. SKILL.md states that the .env file resides in the Skill working directory, so reading .env files from arbitrary parent projects or shared runtime directories is unnecessary. A fixed Skill-local path would provide all filesystem access required by the declared functionality.

If the Skill-local .env file is absent, credentials with matching names from an unrelated ancestor configuration can be sile ...[truncated 2175 chars]

Remediation
View remediation

Remediation Suggestions

  1. Restrict credential-file access to the documented Skill-local .env file:

    javascript
    function readEnvFile() {
        const envConfig = {};
        const envPath = path.resolve(__dirname, '..', '.env');
    
        if (!fs.existsSync(envPath)) {
            return envConfig;
        }
    
        const content = fs.readFileSync(envPath, 'utf8');
        content.split('\n').forEach(line => {
            const accessMatch =
                line.match(/^\s*DS_ACCESS_KEY\s*=\s*"?([^"]*)"?\s*$/);
            const secretMatch =
                line.match(/^\s*DS_SECRET_KEY\s*=\s*"?([^"]*)"?\s*$/);
    
            if (accessMatch) {
                envConfig.DS_ACCESS_KEY = accessMatch[1].trim();
            }
            if (secretMatch) {
                envConfig.DS_SECRET_KEY = secretMatch[1].trim();
            }
        });
    
        return envConfig;
    }
    
  2. Do not traverse above the Skill root under any circumstances.

  3. Prefer credentials supplied through a dedicated secret manager or explicitly injected process environment variables.

  4. If configurable file locations are required, accept an explicit trusted path and validate it against an approved configuration directory.

  5. Reject ambiguous configurations rather than silently selecting the first ancestor .env file.

  6. Keep the secret key local to HMAC generation, never log authentication headers, and ensure diagnostic errors do not include credential values.

  7. Add tests verifying that .env files outside the Skill root are never read.

Vulnerability Patterns
  • 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
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (21)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

text
dexscan-skill/
├── SKILL.md              # 主技能文件(当前文件)
├── .env                  # API 密钥配置文件
├── scripts/
│   └── dexscan.js        # API 调用脚本(get/post封装+签名认证)
├── references/

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/dexscan.js (reported line 107)May include surrounding context.

js
```
dexscan-skill/
├── SKILL.md              # 主技能文件(当前文件)
├── .env                  # API 密钥配置文件
├── scripts/
│   └── dexscan.js        # API 调用脚本(get/post封装+签名认证)
├── references/

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/dexscan.js (reported line 119)May include surrounding context.

js
```
dexscan-skill/
├── SKILL.md              # 主技能文件(当前文件)
├── .env                  # API 密钥配置文件
├── scripts/
│   └── dexscan.js        # API 调用脚本(get/post封装+签名认证)
├── references/

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

The credential-access finding is valid because the skill implements logic to search for and read .env files outside its own directory context. In an agent or shared workspace, this can unintentionally capture secrets belonging to other applications, expanding the blast radius far beyond what a market-data integration should need.

Content

Scanner excerpt · scripts/dexscan.js (reported line 19)May include surrounding context.

js
const path = require('path');
const BASE_URI = 'https://openapi.dexscan.trade';

// 读取 .env 文件,从 dexscan-skill 目录向上逐级查找直到根目录
function readEnvFile() {
    const envConfig = {};
    let currentDir = __dirname;

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

The loop beginning here performs unbounded upward discovery of .env files until the filesystem root. That behavior constitutes overly broad credential access because any parent-level secret file becomes eligible for use by this skill, even if it was never intended to trust or serve this component.

Content

Scanner excerpt · scripts/dexscan.js (reported line 24)May include surrounding context.

js
const envConfig = {};
    let currentDir = __dirname;

    // 向上逐级查找 .env 文件,直到根目录
    while (true) {
        const envPath = path.join(currentDir, '.env');
        if (fs.existsSync(envPath)) {

Credential Access

High
Category
Privilege Escalation
Confidence
96% confidence
Finding

This readFileSync call consumes the contents of the discovered .env file once found, confirming actual secret material access rather than a mere existence check. Combined with ancestor traversal, it can pull credentials from unrelated repositories or deployment roots and silently apply them to outbound authenticated requests.

Content

Scanner excerpt · scripts/dexscan.js (reported line 26)May include surrounding context.

js
// 向上逐级查找 .env 文件,直到根目录
    while (true) {
        const envPath = path.join(currentDir, '.env');
        if (fs.existsSync(envPath)) {
            const content = fs.readFileSync(envPath, 'utf-8');
            content.split('\n').forEach(line => {

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding

The skill documents use of network access and environment-based secrets, but it does not declare any explicit tool scope such as allowed-tools or permissions. This creates an over-privileged integration surface where an agent may invoke networked code and access secrets without clear policy boundaries, increasing the risk of unintended external requests or secret exposure through downstream behavior.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The trigger conditions are very broad and match generic cryptocurrency topics such as price, market cap, volume, token search, and address search. This can cause the skill to activate in many ordinary conversations, unnecessarily granting a networked, secret-using skill influence over prompts where it may not be needed, which expands attack surface and increases the chance of accidental data handling or unintended calls.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The documented response includes address labels such as DEV/KOL/TOP10/SNIPER/NEW and related tag metadata without any warning or minimization guidance. In a skill designed to surface on-chain intelligence, this can facilitate profiling, deanonymization, and redistribution of potentially sensitive attribution data, especially when users request detailed output by default or without understanding the privacy implications.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The developer-token detailed output explicitly includes appendix fields with external profile links and contact data such as email, but the documentation provides no warning that these fields may expose personal or off-chain identifying information. This increases the risk of harassment, scraping, or correlation of on-chain developer activity with off-chain identities.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The rank output documentation allows detailed disclosure of social tag info, high-profit coins, and AI-generated labels/summaries without warning that these are profiling and enrichment signals. In this context, combining profitability rankings with identity-like metadata can enable targeted surveillance, copy-trading exploitation, or reputational harm based on inferred behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The search API explicitly supports wallet-address queries and returns trader/profile-style data such as activity time, volume, realized PnL, and social tag metadata. Even if the data is sourced from public blockchain and social sources, exposing it through a skill without any privacy notice, use limitation, or abuse guidance increases the risk of user de-anonymization, profiling, and targeted surveillance at scale.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The skill exposes wallet-address-level transaction history, behavioral tags, and profit/loss analytics without documenting privacy, sensitivity, or user-warning requirements. In a blockchain analytics context this can facilitate deanonymization, profiling, targeted harassment, or misuse of trader intelligence, especially when combined with labels like KOL, DEV, TOP10, or source-address metadata.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The code walks upward from the skill directory to the filesystem root looking for a .env file, then reads DS_ACCESS_KEY and DS_SECRET_KEY from the first match it finds. That gives this market-data skill broader file-system reach than necessary and can cause it to ingest credentials from parent projects or unrelated environments, which is a real credential boundary violation if the skill runs inside a larger workspace.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This code file sends GET and POST requests to an external API and includes authentication headers derived from DS_ACCESS_KEY and DS_SECRET_KEY, while also transmitting caller-provided parameters such as wallet addresses, token contract addresses, and tweet IDs. Although the code has internal docstrings, it provides no confirmation prompt, user-facing log, or explicit disclosure that sensitive query inputs and auth material will be sent to a remote service.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The file presents all operational instructions and API descriptions exclusively in Chinese, with no indication that the skill is region-specific or that users can choose another language. Per SQP-3, forcing a specific language without user opt-in can violate language/locale policy.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

The bulk tweet-heat endpoint retrieves tweet content and engagement metrics for arbitrary tweet IDs, but the documentation provides no warning that this is third-party social-media data subject to platform terms, privacy expectations, and possible misuse. In context this is less severe than direct secret leakage, but it still enables easy aggregation and redistribution of social data without transparency or safeguards.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The entire skill reference forces a single language/locale in its natural-language interface and documentation, with no indication that users may choose another language or that the Chinese-only restriction is intentional for a region-specific tool. This matches the policy category for language or locale constraints without user opt-in.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

L0661 的默认输出要求包含 creatorBalance,但该接口在 L0571-L0619 的响应参数中并未定义该字段,示例响应 L0623-L0657 也没有返回它。这属于文档内部对技能输出意图与实际接口数据结构的不一致,可能误导调用方认为该能力可用。

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

L0897 说明详细信息包含 progress、heat、telegram、twitter 等嵌套数据,但本接口响应参数 L0829-L0864 并未定义 progress 或 heat 结构,只定义了平铺字段如 migrateProgress、twitter、telegram、website。这是文档对返回内容的主动描述与实际定义不一致。

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The file's user-visible natural-language strings and documentation are written exclusively in Chinese, including configuration error messages, with no indication that language choice is configurable or intentionally limited to a Chinese-only audience. Under the language/locale policy, forcing a specific language without user opt-in is a policy concern.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/dexscan.js:105