Back to skill

Security audit

guaikei-douyin-content-index

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its Douyin public-data purpose, but it needs Review because auth errors contradict the docs, the API token is sent in URL query strings, and broad triggers plus default logging create avoidable privacy risk.

Install only if you are comfortable sending Douyin search terms, creator/video URLs, and comment targets to guaikei.com and storing returned datasets locally under logs/. Use a dedicated, revocable token, avoid sensitive or private targets, and review the auth-error contact prompts and query-string token handling before relying on it in shared or regulated environments.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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)

T01 · Skill Instruction Hijacking

Error
Location
src/utils/token.js:23
Finding

Authentication Error Paths Inject Undocumented Promotional and Contact Information into Agent-Visible Output

Content
View full analysis

Vulnerability Details

File Location: src/utils/token.js:23-27; src/utils/request.js:51-56; propagated by src/douyin/search-cli.js:172-197, src/douyin/post-cli.js:83-104, src/douyin/comment-cli.js:82-103, and src/douyin/hot-cli.js:20-39
Vulnerability Type: Runtime instruction and output manipulation
Risk Level: High

Vulnerable Code

js
// src/utils/token.js:23-27
function skillToken(token) {
  if (!isValidToken(token)) {
    utils.printWarn("警告: 你的 GUAIKEI_API_TOKEN 未正确配置,技能已暂停. ");
    utils.printSuccess("\t快速获取通道: www.guaikei.com");
    return "";
  }
js
// src/utils/request.js:51-56
} else if (res.statusCode === 401 || res.statusCode === 403) {
  const e = new AuthError(
    "GUAIKEI_API_TOKEN 无效, 请检查环境变量 或 联系微信: 13395823479 获取解决方案",
  );
  e.noRetry = true;
  reject(e);
js
// src/douyin/search-cli.js:172-197
} catch (error) {
  utils.printError(`搜索失败: ${error.message}`);
  const errorOutput = {
    status: "error",
    error_code: error.code || "UNKNOWN",
    message: error.message,
    timestamp: new Date().toLocaleString(),
    request: {
      command: "search",
      keyword: keyword,
      sort: sort,
      time: time,
      duration: duration,
      content: content,
      limit: limit,
    },
    metadata: {
      skill_version: constants.VERSION,
      runtime_version: process.versions.node,
      execution_time: Date.now() - startTime,
    },
    results: null,
  };
  const exitCode = error.name === "AuthError" ? 3 : 1;
  process.stdout.write(JSON.stringify(errorOutput, null, 2) + "\n", () =>
    process.exit(exitCode),
  );

Technical Analysis

The Skill documentation explicitly states that authentication failures must produce only a neutral error and must not include websites, contact information, or marketing language. The implementation violates that declared security boundary in tw ...[truncated 2268 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove all websites, phone numbers, social-media handles, and promotional language from runtime authentication errors.
  2. Replace both authentication paths with one fixed neutral response, such as:
    js
    const AUTH_MESSAGE =
      "GUAIKEI_API_TOKEN is missing, malformed, invalid, or expired.";
    
  3. Return only a stable error code such as AUTH_ERROR and exit code 3.
  4. Do not copy arbitrary authentication response text into Agent-consumed stdout.
  5. Keep token acquisition and support information exclusively in user-requested documentation.
  6. Add automated tests that invoke every CLI with:
    • no token;
    • a malformed token;
    • a rejected token;
    • an expired token.
  7. Assert that stdout and stderr contain no URL, phone number, social handle, payment direction, or marketing phrase.
  8. Ensure SKILL.md, the implementation, and test expectations remain synchronized.

T09 · Insecure Skill Coding Practices

Warning
Location
src/utils/request.js:94
Finding

API Credential Is Exposed Through URL Query Parameters

Content
View full analysis

Vulnerability Details

File Location: src/utils/request.js:94-120 and src/utils/request.js:123-140; token-bearing callers include src/api/search.js:59-76,104-118, src/api/post.js:23-34,50-59, src/api/comment.js:38-51,67-77, and src/api/hot.js:19-22
Vulnerability Type: Credential exposure through request URLs
Risk Level: Medium

Vulnerable Code

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);
}
js
// src/utils/request.js:123-140
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);
}
js
// src/api/search.js:59-76
const params = {
  _: Date.now(),
  token: token,
};

const 
...[truncated 2185 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove token from all URL parameter objects.
  2. Transmit the token using a standard authorization header:
    js
    headers: {
      Authorization: `Bearer ${token}`,
      "Content-Type": "application/json",
      "Accept-Encoding": "identity",
      "Content-Length": Buffer.byteLength(jsonData),
    }
    
  3. Refactor postJson() and getJson() to accept the token separately from ordinary request parameters so callers cannot accidentally serialize it into a URL.
  4. Configure gateways, proxies, and application logs to redact Authorization, cookies, and any legacy token parameter.
  5. Avoid including credentials in exceptions, retry messages, traces, or diagnostic objects.
  6. Rotate existing tokens because historical access logs may already contain them.
  7. Add tests that intercept outgoing request options and assert that:
    • the request path does not contain token=;
    • the token exists only in the authorization header;
    • logs and errors do not contain the raw token.
  8. Apply least-privilege scopes, expiration, revocation, and quota controls to all issued tokens.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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 (42)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill states it does not read or write user private files, yet it also says logs are automatically written to logs/. Even if intended for operational logging, undisclosed filesystem writes can capture user queries, URLs, or API error details, creating retention and privacy risk beyond the advertised purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill states it does not read or write user private files, yet it also says logs are automatically written to logs/. Even if intended for operational logging, undisclosed filesystem writes can capture user queries, URLs, or API error details, creating retention and privacy risk beyond the advertised purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill states it does not read or write user private files, yet it also says logs are automatically written to logs/. Even if intended for operational logging, undisclosed filesystem writes can capture user queries, URLs, or API error details, creating retention and privacy risk beyond the advertised purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill states it does not read or write user private files, yet it also says logs are automatically written to logs/. Even if intended for operational logging, undisclosed filesystem writes can capture user queries, URLs, or API error details, creating retention and privacy risk beyond the advertised purpose.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
85% confidence
Finding

The skill declares access to an environment variable token (GUAIKEI_API_TOKEN) but does not explicitly declare a tool scope such as allowed tools or permissions. This creates a trust and review gap: the skill can consume sensitive runtime secrets without a clear permission contract, increasing the chance of accidental overexposure or unsafe execution assumptions.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill is designed to activate even when the user does not mention Douyin, which broadens trigger scope and increases the chance of accidental invocation in unrelated contexts. Overbroad activation can lead to unnecessary external data access, command execution, or collection of user intent/data without sufficiently specific consent.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The invocation guidance explicitly permits use even if the user never mentions Douyin, creating ambiguous activation rules. In a skill that can access env-backed credentials and execute Node commands, ambiguous routing raises the risk of unintended third-party queries and unnecessary processing of user requests.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The README tells users to obtain and configure a token, but it does not clearly warn that search keywords, profile URLs, and video/comment targets will be sent to an external service operated via guaikei.com. This weakens informed consent and privacy transparency, particularly because the skill is designed to process user-supplied targets and content-analysis inputs through a third-party API.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The natural-language trigger table maps broad everyday phrases such as '搜索 / 搜一下 / 找' and similar colloquial requests directly to command execution. In an agent setting, this can cause unintended skill invocation when a user is speaking generally, increasing the chance that arbitrary user-provided keywords or URLs are sent to the external Douyin data service without an explicit, informed opt-in.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The intent-recognition rules prioritize generic keywords like '热搜 / 热点 / 榜单 / 搜索 / 找' with minimal disambiguation. This makes accidental activation more likely, especially in multi-skill environments, and can lead to unintended collection/transmission of user queries, target profile URLs, or video links to the external service.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The changelog and feature descriptions are written primarily in Chinese, and there is no indication that users can select another language or that the language restriction is intentional and documented. This may violate a language/locale policy if the broader environment expects user choice rather than a forced locale.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This documentation explicitly supports bulk collection of creator posts and comments, including up to 10,000 records, but provides no warning about privacy, platform terms, retention, or downstream handling of user-generated data. In the context of a data-collection skill, that omission can normalize large-scale scraping and reuse of personal or quasi-personal data without safeguards, increasing compliance and privacy risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The calls to comment.createCommentTask and comment.getCommentTask send user-supplied input and an API token to external services. This code lacks any visible disclosure that network requests will be made with that data, which is relevant because the operation handles user content identifiers and credentials.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The CLI persists fetched comment data to a local JSON file automatically after execution, with no explicit user notice, opt-in, or retention controls in this file. Comment datasets can contain personal data, usernames, or sensitive research material, so silent local storage increases privacy, compliance, and accidental disclosure risk on shared systems or downstream tooling.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This JavaScript file contains multiple natural-language strings in Chinese, starting with the main function comment and continuing through user-facing error and success messages. Because the skill does not offer language selection or indicate that it is intentionally limited to Chinese-speaking users, it may violate the language/locale policy requiring user opt-in or clear justification.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The code persists the full finalOutput payload to disk via log.taskWrite, which includes the request URL and returned results. This file contains no user-facing warning, confirmation prompt, or explanatory comment near the write operation to disclose that data will be stored locally.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The CLI writes the full search output and request metadata, including the user’s keyword and execution details, to a local JSON file by default. Even if the queried data is public, automatic persistence creates an undisclosed data-retention surface that can expose user research activity, sensitive search terms, or collected datasets to other local users, backups, or downstream tooling.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The tool silently writes search results to a local JSON log without explicit user consent or notice. This can leak query intent, result datasets, and timestamps into the filesystem, where they may be accessed by other processes, users, synchronization tools, or backups, especially in shared or managed environments.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This JavaScript file contains user-facing natural language exclusively in Chinese, including comments, error messages, and generated help text. Under the policy, forcing a specific language without user opt-in or a documented locale-specific justification is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This code emits user-facing error text in Chinese only (for invalid filename and content), and later continues this pattern for success/error output. The file provides no indication that the skill is intentionally China/Chinese-specific or that users can opt into another language, which conflicts with the language/locale policy for natural-language behavior.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The surrounding code and manifest describe a Douyin public-data skill, but this inline error text actively instructs users to contact a specific WeChat number to resolve token problems. That embedded guidance is not just incomplete documentation; it changes the apparent intent from a neutral API client to a channel for off-platform credential/support acquisition.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This string hard-codes a Chinese-language remediation message and a WeChat-based support path, which imposes a specific language/locale experience on all users. The policy allows locale constraints only when they are explicitly documented and justified, which is not evident in this file.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The skill documents that logs are automatically saved to logs/, but the user-facing description does not clearly foreground that operational data will be persisted. Even low-sensitivity logs can contain search keywords, video/account URLs, timestamps, and error traces, which creates avoidable privacy and retention risk if users are unaware.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The title and descriptions in the schema use Chinese exclusively, which can impose a language constraint on users without opt-in. The file does not indicate that the skill is region-specific or provide an alternative language option, so this is a natural-language locale policy concern.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

This JSON schema includes user-facing natural-language title and description fields only in Chinese, with no indication that language selection is optional or region-specific. Under the policy criteria, forcing a specific language without user opt-in can be a locale-policy violation.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.