Back to skill

Security audit

抖音账号订阅追踪 GuaiKei 抖音博主洞察

Security checks for vulnerabilities and agentic risk

Overview

The skill largely matches its Douyin data-analysis purpose, but it handles an API token insecurely and automatically saves collected public user/comment data locally, so it needs review before installation.

Install only if you are comfortable sending Douyin search terms, target URLs, and your GuaiKei API token to www.guaikei.com. Treat the token as sensitive, rotate it if it may have been logged, and avoid using this skill in shared or synced workspaces unless you manage or delete the generated logs 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 (2)

T09 · Insecure Skill Coding Practices

Warning
Location
src/utils/request.js:123
Finding
API token transmitted in URL query parameters<![CDATA[ ## Vulnerability Details **File Location**: `src/utils/request.js:123-140` **Related Locations**: `src/api/search.js:95-120`, `src/api/comment.js:66-80`, `src/api/post.js:49-62`, `src/api/hot.js:16-23` **Vulnerability Type**: Credential exposure through query strings **Risk Level**: Medium ### Evidence The shared GET request function serializes every supplied parameter into the request URL: ```js async function getJson(path, params) { if (!path || typeof path !== "string") { throw new SkillError("PATH_INVALID", "path 必须是非空字符串"); } if (!params || typeof params !== "object") { throw new SkillError("PARAM_INVALID", "params 必须是对象"); } params._ = Date.now(); const fullPath = `${path}?${querystring.stringify(params)}`; const options = { host: constants.BASE_URL, path: fullPath, method: "GET", headers: { "Accept-Encoding": "identity" }, }; return await request(options); } ``` API callers include the secret token in that parameter object. For example: ```js const params = { _: Date.now(), token: token, keyword: keyword, sort_type: sort, publish_time: time, filter_duration: duration, content_type: content, limit: limit, }; const response = await requestApi( "GET", "/api/douyin/general-search/info", params, null, constants.QUERY_MAX_ATTEMPTS, "查询任务", ); ``` Equivalent query-string authentication is used for comment, creator-post, and hot-list requests. ### Technical Analysis The token from `GUAIKEI_API_TOKEN` becomes part of request targets such as: ```text /api/douyin/general-search/info?token=<secret>&keyword=<value>&... ``` HTTPS encrypts the request target while it is in transit, so a passive network observer cannot ordinarily read it. However, credentials in URLs are commonly retained by infrastructure that records request targets, including: - API server access logs; - reverse-proxy and load-balancer logs; - application performance monitoring and tracing systems; - debu ...[truncated 1833 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `token` from all URL parameter objects. 2. Transmit the credential in an HTTP authorization header, for example: ```js headers: { Authorization: `Bearer ${token}`, "Accept-Encoding": "identity", } ``` 3. Refactor `getJson()` and `postJson()` to accept authentication separately from ordinary request parameters. 4. Add a defensive check that rejects sensitive query keys such as `token`, `api_key`, `authorization`, and `secret`. 5. Configure the API server and intermediary infrastructure to redact query strings from historical and future access logs. 6. Rotate all existing tokens because previous requests may already have been retained in server or proxy logs. 7. Apply short token lifetimes, scoped API permissions, rate limits, and revocation support. 8. Add automated tests that assert generated request paths never contain the token value. 9. Avoid including user search terms and target URLs in GET query strings when they may be sensitive; use a POST body where practical. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
src/douyin/comment-cli.js:145
Finding
Automatic plaintext persistence of query results and public personal data<![CDATA[ ## Vulnerability Details **File Location**: `src/douyin/comment-cli.js:145-163` **Related Locations**: `src/utils/log.js:27-35`, `src/douyin/search-cli.js:237-260`, `src/douyin/post-cli.js:140-162`, `assets/comment_cli_resp.schema.json:7-42` **Vulnerability Type**: Insecure local storage and excessive data retention **Risk Level**: Medium ### Evidence The comment CLI includes the complete returned comment array in `finalOutput` and prints it: ```js request: { command: "comment", url: url, limit: limit, }, metadata: { skill_version: constants.VERSION, runtime_version: process.versions.node, execution_time: Date.now() - startTime, }, results: commentTask, }; console.log(JSON.stringify(finalOutput, null, 2)); ``` It then automatically writes the same complete object to a persistent file: ```js 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 a project-level `logs` directory and writes the content without an explicit restrictive file mode: ```js try { await fs.promises.mkdir(path.dirname(outputFilename), { recursive: true }); await fs.promises.writeFile(outputFilename, content); utils.printSuccess(` → 已保存到 ${outputFilename}`); } catch (error) { utils.printError(`日志写入失败: ${error.message}`); } ``` According to the response schema, comment records can contain comment text, user IDs, nicknames, stable `sec_uid` identifiers, and an IP-derived region label. Search and creator-post commands similarly persist their complete successful responses. ### Technical Analysis Every successful search, creator-post retrieval, or comment retrieval creates a plaintext JSON file under the project’s `logs` directory. There is no: - explicit user opt-in for persistence; - restrictive file mode such as `0600`; - encryption a ...[truncated 2679 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Make disk persistence opt-in through an explicit option such as `--output <path>` or `--save`. 2. Do not create result files during the default execution path. 3. When persistence is requested, create directories with mode `0700` and files with mode `0600`: ```js await fs.promises.mkdir(outputDirectory, { recursive: true, mode: 0o700, }); await fs.promises.writeFile(outputFilename, content, { mode: 0o600, flag: "wx", }); ``` 4. Redact or omit fields not required for the requested analysis, especially stable user IDs and IP-region labels. 5. Provide configurable retention limits and automatic deletion. 6. Enforce an aggregate storage quota and handle insufficient-disk-space errors safely. 7. Store output outside the source tree in a user-specific application-data directory. 8. Add `logs/` to `.gitignore` and packaging exclusion rules. 9. Clearly notify users before storing personal or user-generated data and document the exact path, fields, retention period, and deletion procedure. 10. Consider encryption at rest where result retention is operationally necessary. 11. Add tests confirming that a normal command does not create persistent files unless the user explicitly requests it. ]]>
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 (38)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill prominently requires a third-party API token and directs users to obtain service access via an external site or direct contact, while the reviewed artifact does not let us verify the promised capabilities. In an agent ecosystem, this kind of unverifiable commercial token-gating can lead users to exfiltrate operational metadata or trust an opaque external dependency without clear scope, especially when the skill handles public social-media data collection.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill prominently requires a third-party API token and directs users to obtain service access via an external site or direct contact, while the reviewed artifact does not let us verify the promised capabilities. In an agent ecosystem, this kind of unverifiable commercial token-gating can lead users to exfiltrate operational metadata or trust an opaque external dependency without clear scope, especially when the skill handles public social-media data collection.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill prominently requires a third-party API token and directs users to obtain service access via an external site or direct contact, while the reviewed artifact does not let us verify the promised capabilities. In an agent ecosystem, this kind of unverifiable commercial token-gating can lead users to exfiltrate operational metadata or trust an opaque external dependency without clear scope, especially when the skill handles public social-media data collection.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The skill prominently requires a third-party API token and directs users to obtain service access via an external site or direct contact, while the reviewed artifact does not let us verify the promised capabilities. In an agent ecosystem, this kind of unverifiable commercial token-gating can lead users to exfiltrate operational metadata or trust an opaque external dependency without clear scope, especially when the skill handles public social-media data collection.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The skill prominently requires a third-party API token and directs users to obtain service access via an external site or direct contact, while the reviewed artifact does not let us verify the promised capabilities. In an agent ecosystem, this kind of unverifiable commercial token-gating can lead users to exfiltrate operational metadata or trust an opaque external dependency without clear scope, especially when the skill handles public social-media data collection.

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
70% confidence
Finding
Without declared permissions the skill's intent is opaque and cannot be validated.

Vague Triggers

Medium
Confidence
89% confidence
Finding
The trigger phrases are broad enough to match common requests like analytics, trend analysis, marketing, or content discovery beyond a clearly bounded Douyin-query intent. In an agent setting, overbroad routing can cause the skill to activate on unrelated prompts and send user queries or URLs to a third-party API unnecessarily, increasing privacy and data-minimization risk.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The README states that fetched Douyin data is automatically exported to JSON logs, but it does not clearly warn users that collected video, author, or comment data will persist on local disk. This can create unintended retention of potentially sensitive or regulated content, increasing exposure through shared workstations, backups, log collection systems, or later reuse beyond the user's expectation.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The skill requires a GUAIKEI_API_TOKEN and directs users to configure it, but the README does not clearly disclose that this credential will be sent to an external third-party service to perform requests. Users may incorrectly assume the token is only used locally, which weakens informed consent and increases the risk of credential misuse, leakage, or trust boundary confusion.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
This markdown file is written with a Chinese-only title and the document continues in Chinese, with no indication that users may choose another language or that the skill is intentionally limited to a Chinese-only audience. Under the language/locale policy, forcing a specific language without user opt-in is a natural-language policy concern.

Missing User Warnings

Medium
Confidence
85% confidence
Finding
This function sends the provided token and video URL to an external API endpoint to create a comment task. While the code has developer-facing comments, there is no confirmation prompt, user-facing log, or other disclosure in this file indicating that user data is being transmitted off-system.

Missing User Warnings

Medium
Confidence
82% confidence
Finding
This function performs a GET request to a remote API using the token, URL, and limit as request parameters. The operation transmits identifying/request context to an external service, but the file contains no user-facing notice or confirmation about that data sharing.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The CLI persists fetched comment data to a local JSON file automatically, without explicit user consent, visibility, or any controls around where the file is stored. In this skill's context, comment results may contain personal data, usernames, or sensitive moderation/monitoring output, so silent retention increases the risk of unintended disclosure through shared workstations, backups, logs, or later exfiltration.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
This code returns error text in Chinese (for example, "请求失败") as part of user-visible exceptions. The file provides no opt-in, fallback, or justification that the skill is intentionally Chinese-only, which creates a natural-language locale policy issue under the language-choice rule.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The AuthError message is entirely Chinese and appears intended for end users troubleshooting token issues. Because the file does not provide localization or an explicit documented regional scope, this is a language policy violation rather than just an implementation detail.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
The user-facing strings in this file are entirely in Chinese, including warnings and status messages, with no indication that language is configurable or that the skill is intended only for a Chinese-speaking or region-specific context. This creates a natural-language locale policy issue because the skill imposes a specific language on users without opt-in.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
This manifest-style JSON schema contains user-facing natural language fields such as title and description entirely in Chinese. Because the file provides no opt-in, alternative language, or documented region-specific justification, it may violate language/locale policy requirements for offering choice or documenting constraints.

Natural-Language Policy Violations

Low
Confidence
81% confidence
Finding
The schema title and description are written only in Chinese, which can constitute a language/locale policy issue when a skill imposes a specific language without user opt-in or documenting that it is region-specific. In this file there is no accompanying indication that the schema is intentionally limited to Chinese users or Douyin-specific locale requirements.

Natural-Language Policy Violations

Low
Confidence
80% confidence
Finding
This manifest-format JSON schema uses Chinese-only natural-language title and field descriptions throughout, with no indication that the skill is intentionally region-specific or that other language/locale options exist. Under the policy rule, forced language choice without opt-in or documented justification can be a natural-language policy violation.

Natural-Language Policy Violations

Low
Confidence
90% confidence
Finding
The schema's title and field descriptions are written entirely in Chinese, which imposes a specific language on users and integrators. Because the file does not indicate that the skill is region-specific or provide any language/locale alternative, this appears to violate the language-choice policy.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
This JSON schema is a manifest-type file, so natural-language policy checks apply. The title and descriptions consistently force a single language/locale, and there is no indication that this is optional, configurable, or justified as region-specific.

Natural-Language Policy Violations

Low
Confidence
89% confidence
Finding
This JSON schema contains user-facing title and description strings only in Chinese, which can impose a fixed language on users or downstream tools without any opt-in or documented regional justification. The policy specifically flags language or locale constraints when the skill forces a specific language without user choice.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
This JSON schema uses Chinese-only natural-language titles and descriptions throughout, such as the title and field descriptions, which imposes a specific language on users or downstream tooling. The file does not offer a language choice or explain that the schema is intentionally limited to a Chinese-language or region-specific context.

Natural-Language Policy Violations

Low
Confidence
84% confidence
Finding
The manifest description is entirely in Chinese and presents the skill as a Chinese-only tool, but does not indicate whether users can choose another language or whether the locale restriction is intentional and required. Under the policy, language or locale constraints should be opt-in or clearly justified.

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