Back to skill

Security audit

抖音数据分析 Guaikei 作品搜索

Security checks for vulnerabilities and agentic risk

Overview

This skill appears purpose-aligned, but it handles an API token in a risky way and automatically saves retrieved social-media data locally.

Before installing, confirm you are comfortable sending Douyin keywords, target URLs or IDs, and your GuaiKei API token to guaikei.com. Treat the token carefully because this version puts it in request URLs. Also review or delete the local logs directory after use, since exported JSON may include public usernames, profile IDs, comments, URLs, and research targets.

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
src/utils/request.js:105
Finding
API Token Transmitted in URL Query Strings<![CDATA[ ## Vulnerability Details **File Location**: - `src/api/search.js:59-62` - `src/api/search.js:104-114` - `src/api/comment.js:38-41` - `src/api/comment.js:67-73` - `src/api/post.js:23-26` - `src/api/post.js:50-55` - `src/api/hot.js:18-22` - `src/utils/request.js:94-120` - `src/utils/request.js:123-140` **Vulnerability Type**: Credential exposure through URL query parameters **Risk Level**: Medium ### Vulnerable Code The API modules add the secret token to request parameters: ```js // src/api/search.js:59-62 const params = { _: Date.now(), token: token, }; ``` The token is also included in GET requests together with user input: ```js // src/api/search.js:104-114 const params = { _: Date.now(), token: token, keyword: keyword, sort_type: sort, publish_time: time, filter_duration: duration, content_type: content, limit: limit, }; ``` The common HTTP client serializes all parameters, including the token, into the URL: ```js // src/utils/request.js:94-120 async function postJson(path, params, data) { if (!path || typeof path !== "string") { throw new SkillError("PATH_INVALID", "path 必须是非空字符串"); } if (!params || typeof params !== "object") { throw new SkillError("PARAM_INVALID", "params 必须是对象"); } if (!data || typeof data !== "object") { throw new SkillError("DATA_INVALID", "data 必须是对象"); } params.skill_name = skillName(); const fullPath = `${path}?${querystring.stringify(params)}`; const jsonData = JSON.stringify(data); const options = { host: constants.BASE_URL, path: fullPath, method: "POST", headers: { "Content-Type": "application/json", "Accept-Encoding": "identity", "Content-Length": Buffer.byteLength(jsonData), }, }; return await request(options, jsonData); } ``` The same behavior applies to GET requests: ```js // src/utils/request.js:123-140 async function getJson(path, params) { if (!path || typeof path !== "string") { throw new SkillError("P ...[truncated 2534 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `token` from all query-parameter objects. 2. Transmit the token in an authorization header, for example: ```js const options = { host: constants.BASE_URL, path: fullPath, method: "POST", headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json", "Accept-Encoding": "identity", "Content-Length": Buffer.byteLength(jsonData), }, }; ``` 3. Refactor `getJson` and `postJson` to accept authentication separately from ordinary request parameters, preventing accidental serialization into URLs. 4. Ensure request, error, and retry logging redacts `Authorization`, cookies, tokens, and other sensitive headers. 5. Configure the API server, proxies, and monitoring systems not to record credentials or other sensitive query data. 6. Rotate tokens that may already have appeared in URL logs. 7. Prefer short-lived, scoped tokens with explicit rate and permission limits. 8. Add automated tests asserting that generated request paths never contain `token`, `api_key`, or equivalent secret parameters. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
src/utils/log.js:34
Finding
Automatic Persistent Storage of Retrieved Comments, Posts, and Search Results<![CDATA[ ## Vulnerability Details **File Location**: - `src/douyin/search-cli.js:253-261` - `src/douyin/comment-cli.js:151-164` - `src/douyin/post-cli.js:152-162` - `src/utils/log.js:5-39` **Vulnerability Type**: Insecure local retention of collected data **Risk Level**: Low ### Vulnerable Code Successful search results are automatically persisted: ```js // src/douyin/search-cli.js:253-261 console.log(JSON.stringify(finalOutput, null, 2)); utils.printSuccess( `搜索任务完成, 共返回 ${finalOutput.results.length} 条结果`, ); await log.taskWrite( `${startTime}_${keyword}_${sort}_${time}_${duration}_${content}_search.json`, JSON.stringify(finalOutput, null, 2), ); ``` Successful comment results are also written automatically: ```js // src/douyin/comment-cli.js:151-164 console.log(JSON.stringify(finalOutput, null, 2)); utils.printSuccess( `获取评论任务完成, 共返回 ${finalOutput.results.length} 条结果`, ); url = url.replace(/[^a-zA-Z0-9_-]/g, ""); url = url.replace("httpswwwdouyincomvideo", ""); url = url.replace("httpswwwdouyincomnote", ""); await log.taskWrite( `${startTime}_${url}_comment.json`, JSON.stringify(finalOutput, null, 2), ); ``` The logging utility creates the destination and writes the complete content using ambient default permissions: ```js // src/utils/log.js:5-39 async function taskWrite(filename, content) { if (!filename || typeof filename !== "string") { utils.printError("日志文件名必须是非空字符串"); return; } if (!content || typeof content !== "string") { utils.printError("日志内容必须是非空字符串"); return; } let safeFilename = filename .replace(/[\\/:*?"<>|]/g, "_") .replace(/\.\.+/g, "_") .replace(/^\.+|\.+$/g, ""); if (safeFilename.length > 200) { safeFilename = safeFilename.slice(0, 200); } if (!safeFilename) { safeFilename = `log_${Date.now()}`; } const outputFilename = path.join( path.dirname(__filename), "..", "..", "logs", safeFilename, ); try { await fs.promises.mkdir(path.dirname ...[truncated 2410 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Make disk persistence opt-in through an explicit option such as `--output` or `--save`. 2. Default to returning results only through standard output. 3. When persistence is requested, create the directory and files with restrictive permissions: ```js await fs.promises.mkdir(logDirectory, { recursive: true, mode: 0o700, }); await fs.promises.writeFile(outputFilename, content, { mode: 0o600, flag: "wx", }); ``` 4. Warn users before storing comments, identifiers, or other potentially sensitive datasets. 5. Provide configurable retention periods and a cleanup command. 6. Minimize stored content by allowing users to select fields and by omitting unnecessary request metadata. 7. Add `logs/` to `.gitignore` and exclude it from package publication, CI artifacts, backups, and synchronization by default. 8. Consider encryption at rest when results must be retained in shared or managed environments. 9. Document local privacy responsibilities and recommend de-identification before sharing or publishing exported data. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (45)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
声明描述的是一个面向抖音的数据分析/检索技能,核心能力应涉及访问抖音相关数据源、执行搜索、抓取作品、获取评论或返回热榜信息。但提供的代码仅是通用参数解析模块(parseArgs、readValueAfterFlag、buildHelp),作用是处理 CLI 输入和帮助文案生成。它没有任何网络请求、抖音 API/页面访问、数据抓取、搜索实现、评论分析或热榜处理逻辑。因此该代码块的实际行为与声明用途存在明显且实质性的不匹配。

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
声明描述的是一个面向抖音的数据查询与分析技能,但提供的代码片段只是本地日志写入模块,没有任何与抖音平台、网络请求、搜索、热榜、作者作品或评论数据处理相关的行为。虽然日志记录可能是整个技能的辅助实现细节,但就该代码片段本身而言,其实际功能与声明的业务能力明显不一致;此外,该片段涉及本地文件系统写入这一未在描述中体现的行为。因此应判定为描述与代码行为不匹配。

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
声明描述的是一个面向抖音的数据检索与分析技能,涵盖多个外部数据查询能力。但给定代码片段只包含一个 skillName() 函数,通过 fs 和 path 读取本地 package.json 并返回包名。这与声明的核心能力没有直接对应关系,也未体现任何抖音相关数据访问、搜索、抓取或分析逻辑。虽然这可能是辅助模块,但就该代码片段本身而言,其行为与声明用途明显不一致。

Credential Access

High
Category
Privilege Escalation
Content
- 技能重命名为“douyin-search-keyword”。
- 在SKILL.md中添加了openclaw元数据、使用帮助、许可证、标签和示例,以实现更好的集成与文档化。
- 移除了两个本地文件(.env 和 scripts/last-search.json),以优化代码结构并提升安全性。
- 文档现已更加简洁且以用户为中心,重点在于提供清晰的使用说明和数据字段解释。
- 突出技能特性、合规要点及技术流程。
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding
The skill declares access to a sensitive environment variable (`GUAIKEI_API_TOKEN`) but does not define any explicit tool scope or permission boundary. In agent systems, undeclared or over-broad capability exposure increases the risk that the token could be accessed or misused by skill code or by future modifications without clear review constraints.

Vague Triggers

Medium
Confidence
93% confidence
Finding
The trigger phrase list includes broad activations such as analytics, competitor analysis, trend analysis, and social listening terms that can match user requests not specifically asking for Douyin data retrieval. Over-broad activation can cause the wrong skill to run, leading to unintended data access, unnecessary third-party data disclosure, or bypass of more appropriate safer routing.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The README states that fetched Douyin data is automatically exported to local log files, including comments and account-related outputs, but it does not clearly warn users that this data may contain personal or sensitive information and will persist on disk. In a scraping/analytics skill, silent persistence increases the risk of unintended retention, local exposure, and secondary misuse of collected data.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The documentation requires a GUAIKEI_API_TOKEN and directs users to a third-party service, but it does not clearly disclose that user queries, target URLs/IDs, and retrieved platform data will be transmitted to that external provider. This lack of transparency can lead users to expose research targets or collected social-media data to a third party without informed consent or proper data-handling review.

Natural-Language Policy Violations

Medium
Confidence
84% confidence
Finding
The file begins with a fully Chinese title and the changelog entries are predominantly written in Chinese, with no indication that the skill supports other languages or that Chinese-only content is a required regional constraint. This can violate language/locale policy when the skill documentation effectively forces one language without user opt-in.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The entire skill documentation, including headings, parameter descriptions, and examples, is presented only in Chinese. Under the policy criteria, forcing a specific language without user opt-in or a clearly documented regional justification is a natural-language policy violation.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The CLI persists the full comment query output to a local JSON file after printing it, which can retain potentially sensitive or regulated user-generated content beyond the immediate task. Because this happens automatically and without retention controls, consent, redaction, or access restrictions, it increases the risk of local data exposure, unintended reuse, and privacy violations.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The code writes comment results to a local JSON file without any user-facing warning, confirmation, or explicit opt-in, which creates a stealthy data retention path. In the context of a social-media analysis skill that collects comment content and interaction data, this makes privacy and compliance risk higher because operators may not realize data is being stored on disk.

Description-Behavior Mismatch

Medium
Confidence
88% confidence
Finding
The manifest presents this skill as a Douyin search, hot-list, author-post, and comment-analysis tool focused on data retrieval and analytics. This file implements persistent local filesystem writes to a logs directory, which is not mentioned in the manifest and goes beyond the described query/analysis behavior.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The skill emits user-facing error messages in Chinese strings such as "日志文件名必须是非空字符串" and "日志内容必须是非空字符串". Because the file provides no opt-in, fallback, or documentation that this is a China/Chinese-specific skill, this creates a natural-language locale policy violation.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The strings "已保存到" and "日志写入失败" are hard-coded user-visible messages in Chinese. For a general-purpose utility file, forcing a specific language without offering a choice or stating a justified regional scope violates the language/locale policy criteria.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
Multiple error messages are presented only in Chinese, including authentication and network failures, without offering a language choice or documenting a locale-specific constraint. If the organization requires user language opt-in, these fixed Chinese-only strings are a natural-language policy concern.

Missing User Warnings

Medium
Confidence
83% confidence
Finding
This code performs outbound HTTPS GET and POST requests and includes arbitrary params in the URL query string and data in the request body. While the file has an API docstring and retry logging, there is no user-facing warning, confirmation, or comment disclosing that user or system data may be sent over the network.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
All user-facing warnings and status messages in this file are hard-coded in Chinese, which can impose a language/locale on users without opt-in. The file does not indicate that the skill is intended only for a Chinese-speaking or region-specific environment, nor does it offer any language selection.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
This JavaScript file contains natural-language comments and error/output strings entirely in Chinese, including validation errors and formatted result text shown to users. Under the policy, forcing a specific language without user opt-in is a locale/language policy violation unless the constraint is explicitly justified, which is not present in this file.

Natural-Language Policy Violations

Low
Confidence
90% confidence
Finding
This manifest/config file contains natural-language titles and descriptions exclusively in Chinese, which can impose a language requirement on users without any documented opt-in or justification. The policy calls for flagging language or locale constraints when the skill does not offer a choice or clearly document the regional limitation.

Natural-Language Policy Violations

Low
Confidence
87% confidence
Finding
This JSON schema contains user-facing natural-language strings entirely in Chinese, including the title and descriptions for each field. Under the stated policy, forcing a specific language without user opt-in or a documented regional justification can be a locale-policy violation.

Natural-Language Policy Violations

Low
Confidence
87% confidence
Finding
This JSON schema uses Chinese-only natural-language titles and descriptions throughout, including the top-level title/description and field descriptions. Because the file provides no indication that the skill is region-specific or that language selection is intentional, it may violate the policy against forcing a specific language without user opt-in.

Natural-Language Policy Violations

Low
Confidence
87% confidence
Finding
The title and description fields are written entirely in Chinese, including parameter descriptions, which can impose a language-specific interaction on users without indicating that the skill is China-region or Chinese-language only. This is a natural-language locale policy concern because the file provides no opt-in, alternative language, or documented justification for the restriction.

Natural-Language Policy Violations

Low
Confidence
86% confidence
Finding
This JSON schema uses Chinese-only natural-language titles and descriptions throughout, including the top-level title/description and field descriptions. Because no opt-in, alternative locale, or justification for a China-specific scope is provided in the file, it appears to impose a specific language/locale in a way that may violate organizational language-choice policy.

Natural-Language Policy Violations

Low
Confidence
90% confidence
Finding
The title and descriptions are written entirely in Chinese, which imposes a specific language on users of the skill schema. The file does not indicate that the skill is China-specific or that users can opt into this locale, so it creates a natural-language locale policy concern.

Static analysis

Detected: suspicious.exposed_secret_literal

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
SKILL.md:24