Back to skill

Security audit

quotedance-market

Security checks for vulnerabilities and agentic risk

Overview

This market-report skill is mostly purpose-aligned, but it handles API and proxy credentials in ways that can expose them in logs or process arguments.

Review this skill before installing if you use authenticated proxies or a quotedance API key. Avoid running --net-debug with credential-bearing proxy URLs, consider disabling curl fallback, and use narrowly scoped or disposable API keys until the logging and curl fallback paths redact or avoid secrets.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (3)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/market-scan.js:764
Finding

Authenticated Proxy URL Disclosed Through Network Diagnostics

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/market-scan.js:137
Finding

API Key May Be Exposed Through Curl Arguments and Failure Logs

Content
View full analysis
{ args.push('-H', k + ': ' + v); }); if (PROXY_URL) { args.push('--proxy', PROXY_URL); } return execFileSync('curl', args, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }); } ``` The quotedance API key is placed in those headers: ```js function getApiHeaders() { const headers = { Accept: 'application/json' }; const key = CONFIG.apiKey || process.env.QUTEDANCE_API_KEY || ''; if (key) headers['X-API-Key'] = key; return headers; } ``` Errors are subsequently logged without sanitization: ```js async function safeCall(label, runner, fallback) { try { return await runner(); } catch (e) { log(label + '失败: ' + (e.message || e)); return fallback; } } ``` ### Technical Analysis When native HTTP requests fail, `curlFetch` places the `X-API-Key` value in curl's argument vector through `-H`. Command-line arguments can be visible to other local processes through process inspection facilities while curl is running. If `execFileSync` fails, the resulting Node.js error can also contain command and argument details. The enclosing error handling logs `e.message` without removing header values, proxy credentials, or other sensitive arguments. This creates a second potential disclosure path into persistent logs or Agent-visible output. Using `execFileSync` with an argument array prevents ordinary shell metacharacter injection, so this finding is credential exposure rather than shell-command injection. ### Attack Path 1 ...[truncated 1059 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
scripts/market-scan.js:137
Finding

Curl Fallback Bypasses Configured Proxy Routing Policy

Content
View full analysis
{ args.push('-H', k + ': ' + v); }); if (PROXY_URL) { args.push('--proxy', PROXY_URL); } return execFileSync('curl', args, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }); } ``` Native requests calculate a per-request routing decision: ```js async function fetchJson(url, headers = {}, timeoutMs = REQUEST_TIMEOUT_MS) { const useProxy = shouldUseProxy(url); const maxTry = Math.max(1, REQUEST_RETRIES + 1); let lastError = null; for (let i = 0; i < maxTry; i++) { try { const res = await fetchWithTimeout(url, headers, timeoutMs, useProxy); return await res.json(); } catch (e) { lastError = e; if (i < maxTry - 1) { await new Promise(r => setTimeout(r, 300 * (i + 1))); } } } if (ENABLE_CURL_FALLBACK) { try { const body = curlFetch(url, headers, timeoutMs); return JSON.parse(body); } catch (e) { lastError = e; } } throw lastError || new Error('fetch json failed'); } ``` ### Technical Analysis Native fetch calls `shouldUseProxy(url)` and passes the resulting decision to `fetchWithTimeout`. In contrast, `curlFetch` receives no `useProxy` parameter and adds `--proxy` whenever any proxy URL is available. Consequently, curl fallback can proxy a request even when `network.useProxy` is `false`. It also ignores any intended domain-specific routing policy. The fallback behavior therefore differs from the primary request behavior and exceeds the network exposure implied by the configuration. The default project configuration currently sets `network.us ...[truncated 1315 chars]
Remediation
View remediation
{ args.push('-H', `${k}: ${v}`); }); if (useProxy && PROXY_URL) { args.push('--proxy', PROXY_URL); } else { args.push('--noproxy', '*'); } return execFileSync('curl', args, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] }); } ``` Call the fallback using the already computed routing decision: ```js const body = curlFetch(url, headers, timeoutMs, useProxy); ``` ]]>
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (3)

Vague Triggers

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger phrases are broad generic terms like '早报', '晚报', '今日市场', and '整理市场信息', which can appear in ordinary user requests and cause the agent to invoke this skill unexpectedly. In an agent environment, overbroad activation can route unrelated conversations into external-data-fetching workflows, increasing the chance of unintended network access, confusing responses, or context hijacking.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The skill is presented entirely as a Chinese-language market research assistant for global markets, with no indication that users may choose another language or locale. This can constitute a language/locale policy issue because the skill appears to impose a specific language experience without explicit user opt-in or documented regional justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code explicitly formats numeric output using the zh-CN locale, and the generated report text throughout the file is also hard-coded in Chinese. This enforces a specific language/locale without any visible opt-in or fallback, which matches the language/locale policy violation criteria.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dangerous_exec, suspicious.env_credential_access

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/market-scan.js:154

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/market-scan.js:28