Back to skill

Security audit

qutedance-quotes

Security checks for vulnerabilities and agentic risk

Overview

The skill appears purpose-built for market quote lookup, but it encourages storing an API key in a local config file, which users should review before installing.

Install only if you are comfortable with this skill calling the configured Qutedance service for market data. Do not put a real API key in config.json; use QUTEDANCE_API_KEY or another secret mechanism, and rotate any key that may already have been saved or shared in the skill directory.

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 (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/qutedance-quotes.js:25
Finding
Plaintext API Key Storage in Tracked Configuration Is Encouraged and Prioritized## Vulnerability Details **File Location**: `scripts/qutedance-quotes.js:25-28`; related documentation at `SKILL.md:20-22` and configuration field at `config.json:3` **Vulnerability Type**: Plaintext secret storage and insecure credential precedence **Risk Level**: Medium ### Vulnerable Code ```js const API_KEY = CONFIG.apiKey || process.env.QUTEDANCE_API_KEY || ''; ``` Related documented configuration: ```json { "serviceUrl": "https://quotedance.api.gapgap.cc", "apiKey": "" } ``` The documentation explicitly directs users to place the API key in the configuration file for convenience. The distributed configuration currently contains an empty value, so no active credential was exposed in the audited artifact. ### Technical Analysis The implementation reads `apiKey` from the repository-local `config.json` before checking the `QUTEDANCE_API_KEY` environment variable. This design encourages users to save a live credential as plaintext inside the Skill directory and makes the less secure source take precedence over the safer environment-based mechanism. A populated configuration file can subsequently be committed to source control, included in backups or archives, copied with the workspace, or disclosed when the Skill directory is shared. The script then transmits the key in the `X-API-Key` header over HTTPS to the declared Qutedance service. That network transmission is necessary for the documented authentication flow and is not, by itself, covert exfiltration; the security issue is the credential's persistent plaintext storage. ### Attack Path 1. A user follows the documentation and writes a valid Qutedance API key into `config.json`. 2. The plaintext configuration is committed, archived, backed up, or shared with the Skill directory. 3. An unauthorized party obtains read access to that copy and extracts the API key. 4. The party submits the stolen key in an `X-API-Key` header to the configure ...[truncated 890 chars]
Remediation
## Remediation Suggestions 1. Remove support for credentials stored in tracked `config.json`, or reserve that file exclusively for non-sensitive settings. 2. Read the key from `QUTEDANCE_API_KEY` or a platform-managed secret store: ```js const API_KEY = process.env.QUTEDANCE_API_KEY || ''; ``` 3. Update `SKILL.md` to instruct users never to place credentials in repository files. 4. If file-based secrets are operationally necessary, use a separate untracked file with restrictive filesystem permissions and add it to `.gitignore`. 5. Provide only a redacted example configuration, such as `config.example.json`, without an `apiKey` value. 6. Fail with a clear message when authentication is required but no key is available; never print the key in errors or logs. 7. Scan repository history and distributed archives for previously committed keys. Revoke and rotate any credential that may have been exposed. 8. Retain HTTPS certificate verification and restrict the service URL to approved HTTPS origins where deployment requirements permit.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (7)

Missing User Warnings

Medium
Confidence
98% confidence
Finding
The skill explicitly recommends storing the API key directly in config.json 'for simplicity,' which normalizes plaintext credential storage in workspace files. This increases the chance of accidental commit, local disclosure to other tools or users, and reuse of exposed credentials against the external quotedance service.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
This code reads a credential from config.json or QUTEDANCE_API_KEY and later includes it as an X-API-Key header in outbound requests. While the script logs quote retrieval activity, it does not disclose to the user that credentials may be used and transmitted to the configured service.

Natural-Language Policy Violations

Low
Confidence
81% confidence
Finding
The entire skill description, usage guidance, and user utterance examples are presented only in Chinese, which effectively constrains use to a specific language without stating that this is optional or region-specific. Under the policy, a locale or language restriction should be offered as a choice or clearly justified.

Vague Triggers

Low
Confidence
88% confidence
Finding
The '在对话中如何使用' section gives several example utterances and then says the agent should select this skill, but it does not define explicit trigger constraints or negative examples. Because the examples are broad conversational requests like '看下' and '查一下', the invocation scope may be interpreted too loosely in general dialogue.

Intent-Code Divergence

Low
Confidence
86% confidence
Finding
The implementation summary at L135 states the script reads access configuration from `SERVICE_URL` and `QUTEDANCE_API_KEY`, implying environment variables. Earlier, the configuration section at L21-L23 and example config at L28-L35 say the API key is stored directly in `config.json`, so the documentation presents contradictory statements about how credentials are sourced.

Natural-Language Policy Violations

Low
Confidence
92% confidence
Finding
The default value `"type": "cn"` appears to enforce a China-specific locale or content type in configuration. This is a natural-language policy concern because the file provides no indication that users can choose a different locale or explicitly opt in to this setting.

Natural-Language Policy Violations

Low
Confidence
84% confidence
Finding
The natural-language description and user-facing usage strings are written exclusively in Chinese, which effectively constrains the skill to a specific language without any opt-in or alternative. Under the stated policy, language constraints should be optional or explicitly justified.

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/qutedance-quotes.js:27