Back to skill

Security audit

腾讯广告妙问

Security checks for vulnerabilities and agentic risk

Overview

This Tencent Ads skill is broadly purpose-aligned, but it handles API keys unsafely and can upload arbitrary local files to a remote service.

Review before installing. Only use this skill if you trust the publisher and Tencent/Miaowen endpoints, avoid pasting API keys into chat, prefer setting secrets through a safer local mechanism, and upload only intended advertising materials after checking the exact file path. Rotate any token previously pasted into conversation or passed on a command line.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/setup_token.js:14
Finding
Access Token Exposed Through Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/setup_token.js:14-26`; invocation documented in `references/token_management.md:22-28` **Vulnerability Type**: Sensitive credential exposure through process arguments **Risk Level**: Medium ### Vulnerable Code ```javascript const TOKEN_FILE = path.join(os.homedir(), ".MIAOWEN_ACCESS_TOKEN"); const token = process.argv[2]; if (!token) { console.error("[ERROR] 请提供 Token 参数"); console.error('用法: node setup_token.js "<YOUR_TOKEN>"'); process.exit(1); } // 将 Token 写入文件(覆盖旧内容,不含换行符) try { fs.writeFileSync(TOKEN_FILE, token.trim(), { encoding: "utf-8", mode: 0o600 }); ``` The corresponding documentation explicitly instructs passing the secret as an argument: ```bash node scripts/setup_token.js "<TOKEN_VALUE>" ``` ### Technical Analysis The setup script obtains the Tencent Miaowen access token from `process.argv[2]`. Secrets supplied through command-line arguments can be exposed through: - Process inspection utilities while the command is running. - Shell history. - Agent tool-call histories and execution telemetry. - Command auditing or process-accounting facilities. - Debug and diagnostic logs that record executed commands. The destination file is appropriately created with mode `0600`, and `chmodSync` is subsequently used to reinforce that permission. However, those controls only protect the stored token and do not protect it during command invocation. The Skill documentation also tells the user to paste the token into the conversation and directs the Agent to insert it into a generated shell command. This creates additional opportunities for the credential to remain in conversation history or tool execution records. ### Attack Path 1. The Skill detects a missing or empty token and asks the user to paste a new access token. 2. The Agent follows `references/token_management.md` and executes: `node scripts/setup_token.js "<TOKEN_VALUE>"`. 3. The complete token becomes part ...[truncated 951 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not accept access tokens through command-line arguments. 2. Read the token from standard input or a masked interactive prompt: ```javascript let token = ""; process.stdin.setEncoding("utf8"); process.stdin.on("data", chunk => { token += chunk; }); process.stdin.on("end", () => { saveToken(token.trim()); }); ``` 3. Prefer a terminal input implementation that disables echo when interactive use is required. 4. Update the documentation to use a non-argument workflow, such as: ```bash node scripts/setup_token.js ``` 5. Ensure Agent tool calls, transcripts, and telemetry never record the complete token. 6. Continue creating the destination file with mode `0600`, but also verify ownership and reject unsafe pre-existing targets such as symbolic links. 7. Provide token rotation and revocation guidance in case a token has previously been passed through `argv`. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/upload.js:43
Finding
Unrestricted Local File Upload Exceeds the Declared Material-Review Scope<![CDATA[ ## Vulnerability Details **File Location**: `scripts/upload.js:43-65` and `scripts/upload.js:114-127` **Vulnerability Type**: Unrestricted local file read and authenticated external upload **Risk Level**: Medium ### Vulnerable Code The script accepts any caller-supplied path and only verifies that it resolves to a regular file: ```javascript const filePath = process.argv[2]; if (!filePath) { console.error("[ERROR] 未提供文件路径参数"); console.error("用法: node upload.js <文件路径>"); console.error('示例: node upload.js "/Users/user/images/ad_creative.png"'); process.exit(1); } // 解析为绝对路径 const absolutePath = path.resolve(filePath); if (!fs.existsSync(absolutePath)) { console.error(`[ERROR] 文件不存在: ${absolutePath}`); console.error("请检查文件路径是否正确。"); process.exit(1); } const stat = fs.statSync(absolutePath); if (!stat.isFile()) { console.error(`[ERROR] 路径不是文件: ${absolutePath}`); console.error("请提供一个有效的文件路径,而非目录。"); process.exit(1); } ``` It then reads the complete file and sends it to the remote Tencent endpoint: ```javascript try { // 读取文件内容,构造 FormData const fileBuffer = fs.readFileSync(absolutePath); const fileName = path.basename(absolutePath); // Node.js 18+ 内置 FormData 和 Blob const blob = new Blob([fileBuffer]); const formData = new FormData(); formData.append("file", blob, fileName); const response = await fetch(API_URL, { method: "POST", headers: { Authorization: `Bearer ${token}`, }, body: formData, signal: controller.signal, }); ``` ### Technical Analysis The declared purpose of `upload.js` is to upload images or advertising materials for remote review. However, the implementation accepts every regular local file without enforcing: - An allowlist of supported extensions. - MIME-type validation. - File-signature or magic-byte validation. - A maximum file size. - Restrictions on sensitive directories. - Explicit rejection of symbolic links. - User confirmation of the resolved path before ...[truncated 2065 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Implement an allowlist for supported creative-material formats, such as explicitly approved image and video types. 2. Validate both the filename extension and the actual file signature; do not trust an extension or caller-supplied MIME type alone. 3. Reject symbolic links by using `lstatSync` and verify that the final resolved path remains within an approved user-selected directory. 4. Block sensitive locations such as home credential directories, SSH configuration, cloud credential stores, and system configuration directories. 5. Enforce a strict maximum file size before reading or uploading: ```javascript const MAX_FILE_SIZE = 20 * 1024 * 1024; const stat = fs.lstatSync(absolutePath); if (stat.isSymbolicLink() || !stat.isFile()) { throw new Error("Only non-symbolic-link regular files are allowed"); } if (stat.size > MAX_FILE_SIZE) { throw new Error("File exceeds the upload size limit"); } ``` 6. Stream the file rather than loading the entire contents with `fs.readFileSync`. 7. Before transmission, display the resolved path, detected type, size, and destination, and require explicit user confirmation. 8. Invoke uploads only when the user has expressly requested review of that particular file; do not infer permission to upload unrelated local files. 9. Document retention, access, and deletion behavior for materials stored by the remote service. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • 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 (22)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The declared description presents the skill primarily as a Tencent Ads assistant, but the instructions also include authenticated local token use and uploading arbitrary local files to a remote service. That mismatch is security-relevant because users may authorize or invoke the skill expecting Q&A/analytics behavior, while it can also access sensitive local inputs and exfiltrate them over the network without that being clearly disclosed in the top-level capability description.

Credential Access

High
Category
Privilege Escalation
Content
当脚本退出码为 2(Token 不存在)或 3(Token 为空)时,向用户展示以下指引:

> 🔑 需要先获取妙问 API KEY(Access Token)才能使用。
>
> **获取步骤**:
> 1. 打开 [妙问官网](https://miaowen.qq.com/) 并登录
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Ssd 3

High
Confidence
98% confidence
Finding
The instructions establish a natural-language credential collection workflow by telling the user to paste the API token into the chat. In the context of an agent skill, this is especially dangerous because chat content may be stored, inspected, replayed, or exposed to other tools, turning a sensitive secret into broadly accessible plaintext.

Ssd 3

High
Confidence
99% confidence
Finding
The script explicitly tells the user to paste their Token to the assistant so it can save it. This trains users to disclose bearer credentials in chat, where they may be retained in logs, exposed to intermediaries, or accessed by other tooling, enabling account compromise and unauthorized API use.

Ssd 3

High
Confidence
99% confidence
Finding
This repeats the same unsafe pattern for refreshed tokens, normalizing credential sharing with the assistant. Because the token is a bearer secret for Tencent Ads-related APIs, exposure could let an attacker query account data or perform actions within the scope granted by that token.

Ssd 3

High
Confidence
98% confidence
Finding
The script instructs the user to paste an API token into chat, which encourages disclosure of a bearer credential through a conversational channel that may be logged, retained, or visible to intermediaries. In a skill/agent context this is especially risky because users may assume the assistant can safely handle secrets, leading to credential leakage and subsequent unauthorized API access.

Ssd 3

High
Confidence
98% confidence
Finding
Repeating the instruction to paste a refreshed token into chat reinforces unsafe secret-handling behavior and increases the chance that valid replacement credentials are exposed in logs or to the assistant platform. Because refreshed tokens are active credentials, compromise could let an attacker impersonate the user against the Tencent API until the token is revoked or expires.

Credential Access

High
Category
Privilege Escalation
Content
#!/usr/bin/env node
//
// setup_token.js — 将妙问 Access Token 保存到文件
//
// 用法: node setup_token.js "<YOUR_TOKEN>"
//
Confidence
87% confidence
Finding
The script asks users to pass the access token as a command-line argument, which can expose the credential through shell history, process listings, audit logs, or terminal recording tools. Although the file is later stored with restrictive permissions, the initial input method unnecessarily increases the chance of token disclosure.

Lp3

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding
The skill instructs execution of network-capable scripts (`chat.js`, `api_tool_call.js`, `upload.js`) but does not declare any corresponding tool scope such as network or file access. This creates a transparency and policy-enforcement gap: reviewers, users, or runtime controls cannot accurately understand or constrain what the skill can do, especially since it can send account data and uploaded files to remote Tencent services.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The skill tells the agent to upload a local file to a remote endpoint for audit review, but it does not require an explicit warning or consent flow explaining that the file leaves the local environment and may contain sensitive or proprietary material. In this context, users may submit ad creatives, screenshots, or other business assets, so silent transmission to a third-party service creates clear privacy and confidentiality risk.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The file’s natural-language instructions, parameter descriptions, examples, and notes are all presented in Chinese, and there is no indication that users may choose another language or that the skill is intentionally restricted to a Chinese-speaking or region-specific audience. This can violate language/locale policy when a specific language is effectively forced without user opt-in.

Natural-Language Policy Violations

Medium
Confidence
84% confidence
Finding
The title and all user-facing documentation are written entirely in Chinese, which indicates a fixed locale for the skill experience. Under the policy, forcing a specific language without user opt-in or documented justification is a natural-language policy issue.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This markdown file presents all user-facing field descriptions exclusively in Chinese, starting from the title and continuing through the full dataset. Under the policy, forcing a specific language without user opt-in or a documented justification is a natural-language policy violation.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The document explicitly tells users to paste an API token into the chat, which creates a direct credential disclosure path to the agent and any surrounding logging, retention, or operator access layers. Even if intended for convenience, this is unsafe because API keys are secrets and the guidance omits any warning about sensitivity, storage, or safer alternatives.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
This code file reads a token from ~/.MIAOWEN_ACCESS_TOKEN and sends it to a remote API using a Bearer Authorization header. Although the script documents that it reads a token and makes an API request, it does not include a direct warning that credentials and request data will be transmitted to an external service.

Missing User Warnings

Medium
Confidence
87% confidence
Finding
This code performs an outbound HTTP POST containing the full user-supplied JSON body and Authorization token to an external service. Although the script purpose implies chat functionality, there is no explicit disclosure that prompt contents and credentials are transmitted off-host, which is relevant to user privacy and safety.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
This code performs a network upload of user-supplied file contents and includes a bearer token in the request. Although the script's purpose is upload and it documents usage, it does not provide an explicit warning at execution time or in comments about transmitting local file data and credentials to an external service, which is a safety-relevant disclosure for code files.

Natural-Language Policy Violations

Low
Confidence
87% confidence
Finding
All user-facing instructions in the file are presented in Chinese, with no indication that the user can choose another language or that the skill is intentionally limited to Chinese-speaking users. The policy explicitly flags forced language or locale constraints when there is no opt-in or documented justification.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
The script's usage, errors, and operational guidance are presented entirely in Chinese, which enforces a specific language for users. There is no indication that the language is optional, configurable, or justified as a region-specific constraint.

Natural-Language Policy Violations

Low
Confidence
94% confidence
Finding
The file’s user-facing description, examples, usage guidance, and error/help text are written entirely in Chinese, and lines asking the user to provide a token also assume Chinese interaction. Under the policy, forcing a specific language without user opt-in can be a locale-policy violation unless explicitly justified.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
All user-facing strings, usage instructions, and comments are in Chinese, which effectively imposes a specific language on users. The file does not provide any opt-in, alternative locale, or documentation indicating that the skill is intentionally limited to Chinese-speaking users.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
The script's natural-language comments and console output are consistently written in Chinese, which forces a specific language experience on users. There is no indication of locale selection, fallback behavior, or documentation that this is intentionally limited to Chinese-speaking users.

Static analysis

Detected: suspicious.potential_exfiltration

Sensitive-looking file read is paired with a network send.

Warn
Code
suspicious.potential_exfiltration
Location
scripts/api_tool_call.js:94

Sensitive-looking file read is paired with a network send.

Warn
Code
suspicious.potential_exfiltration
Location
scripts/chat.js:81

Sensitive-looking file read is paired with a network send.

Warn
Code
suspicious.potential_exfiltration
Location
scripts/upload.js:88