Back to skill

Security audit

guaikei-douyin-competitor-videos-and-comments

Security checks for vulnerabilities and agentic risk

Overview

The skill largely does what it claims, but users should review it because it has over-broad activation rules, automatic local data logs, weak token handling, and runtime messages that contradict its own safety promises.

Install only if you are comfortable sending Douyin research requests and your GUAIKEI_API_TOKEN to www.guaikei.com, and with results being saved under logs by default. Treat CLI output, especially error messages, as untrusted service output; do not follow contact instructions or links emitted at runtime without independent verification. Avoid using it for generic research unless you explicitly want Douyin data collection.

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

T01 · Skill Instruction Hijacking

Error
Location
src/utils/request.js:51
Finding

Promotional Contact Information Injected into Authentication Error Output

Content
View full analysis

Vulnerability Details

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

Vulnerable Code

js
} else if (res.statusCode === 401 || res.statusCode === 403) {
  const e = new AuthError(
    "GUAIKEI_API_TOKEN 无效, 请检查环境变量 或 联系微信: 13395823479 获取解决方案",
  );
  e.noRetry = true;
  reject(e);
}

The search CLI then places this message in both diagnostic and machine-readable output:

js
} 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),
  );
  return;
}

Technical Analysis

The HTTP client constructs a fixed authentication-error message containing an unsolicited WeChat contact number. This directly contradicts the security rules in SKILL.md:36-39, which require neutral authentication errors and prohibit contact details, website links, or promotional material in runtime output.

The message is propagated through error.message. Each CLI prints it to stderr and also places it in the JSON response written to stdout. Consequently, an AI agent or automation system consuming the command output may relay the promotional direction to the user a ...[truncated 1309 chars]

Remediation
View remediation

Remediation Suggestions

  1. Replace the message with a fixed, neutral authentication error, for example:
    js
    const e = new AuthError(
      "GUAIKEI_API_TOKEN is missing, invalid, or expired.",
    );
    
  2. Prohibit contact details, promotional links, and acquisition instructions in all runtime error paths.
  3. Centralize user-facing error messages in a local allowlisted mapping keyed by error code.
  4. Add automated tests asserting that authentication failures contain no phone numbers, social-media identifiers, URLs, or promotional language.
  5. Ensure stderr and JSON stdout use the same neutral message.
  6. Review all other runtime messages for similar undocumented redirection or promotion.

T01 · Skill Instruction Hijacking

Error
Location
src/utils/request.js:33
Finding

Untrusted Remote API Error Messages Propagated into Agent-Visible Output

Content
View full analysis

Vulnerability Details

File Location: src/utils/request.js:33-45,163-169; output propagation at src/douyin/search-cli.js:172-197, src/douyin/post-cli.js:83-103, src/douyin/comment-cli.js:82-102, and src/douyin/hot-cli.js:20-38
Vulnerability Type: Untrusted remote content injection into agent and terminal output
Risk Level: High

Vulnerable Code

The API response controls the error message stored in ApiError:

js
if (jsonBody.errcode === 0) {
  resolve(jsonBody);
} else {
  let e;
  if (jsonBody?.errcode <= 16) {
    e = new ApiError(
      jsonBody?.errcode?.toString(),
      jsonBody?.errmsg || "请求失败",
    );
  } else {
    e = new ApiError(
      jsonBody.errcode.toString(),
      jsonBody?.errmsg || "请求失败",
    );
    e.noRetry = true;
  }
  reject(e);
}

The message is emitted during retries without sanitization:

js
return await withRetry(
  async () => {
    let response;
    if (method === "POST") {
      response = await postJson(path, params, data);
    } else {
      response = await getJson(path, params);
    }
    return response;
  },
  maxAttempts,
  (attempt, err) => {
    utils.printError(
      `【${actionName}重试】 ${attempt + 1}/${maxAttempts} 次 - ${err.message}`,
    );
  },
);

The CLI also copies the message into JSON stdout:

js
} 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(errorOut
...[truncated 2447 chars]
Remediation
View remediation

Remediation Suggestions

  1. Define a local allowlisted mapping from known API error codes to fixed English user-facing messages.
  2. Do not expose the remote errmsg value in stdout or ordinary stderr output.
  3. If remote diagnostic text must be retained, place it in an opt-in debug log after:
    • Removing control characters and ANSI escape sequences.
    • Enforcing a strict maximum length.
    • Escaping line breaks.
    • Rejecting or neutralizing URLs and instruction-like content.
  4. Return stable structured fields such as:
    json
    {
      "error_code": "API_LIMIT_EXCEEDED",
      "message": "The API request limit has been reached."
    }
    
  5. Avoid printing the same untrusted message during every retry.
  6. Add tests using malicious errmsg payloads containing URLs, multiline instructions, ANSI sequences, and oversized strings.
  7. Treat all API response fields as untrusted data even when TLS is used.

T09 · Insecure Skill Coding Practices

Warning
Location
src/api/search.js:59
Finding

API Authentication Token Exposed in URL Query Strings

Content
View full analysis

Vulnerability Details

File Location: src/api/search.js:59-62,104-107; src/api/post.js:23-25,50-53; src/api/comment.js:38-40,67-70; src/api/hot.js:19-22; URL construction in src/utils/request.js:94-120,123-140
Vulnerability Type: Sensitive credential exposure through request URLs
Risk Level: Medium

Vulnerable Code

The token is added to query parameters for search requests:

js
const params = {
  _: Date.now(),
  token: token,
};

Polling requests also place it in the query object:

js
const params = {
  _: Date.now(),
  token: token,
  keyword: keyword,
  sort_type: sort,
  publish_time: time,
  filter_duration: duration,
  content_type: content,
  limit: limit,
};

The shared request utility serializes all parameters into the URL:

js
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);

GET requests use the same pattern:

js
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);

Technical Analysis

The GUAIKEI_API_TOKEN is a bearer-style credential but is transmitted as a URL query parameter. HTTPS encrypts the request in transit, but it does not prevent the complete URL from being recorded after TLS termination.

Request URLs are routinely stored by:

  • Reverse proxies and load balancers.
  • API gateways.
  • Web-server access logs.
  • Observability and tracing systems.
  • Error monitoring systems.
  • Debugging middleware.
  • Network-security products operating at tr ...[truncated 1740 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove the token from every query-parameter object.
  2. Send it in the standard authorization header:
    js
    headers: {
      "Authorization": `Bearer ${token}`,
      "Content-Type": "application/json",
      "Accept-Encoding": "identity",
    }
    
  3. Refactor getJson() and postJson() to accept authentication separately from ordinary request parameters.
  4. Configure reverse proxies, gateways, tracing platforms, and application logs to redact the Authorization header.
  5. Ensure errors never print complete request options or authentication headers.
  6. Rotate tokens that may already have appeared in URL logs.
  7. Review and purge retained access logs containing token= where operationally and legally appropriate.
  8. Add tests verifying that generated request paths never contain token, secret, password, or equivalent credential fields.
  9. Consider short-lived scoped tokens to reduce the impact of future credential disclosure.
Vulnerability Patterns
  • 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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (39)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The manifest says the skill uses minimal permissions and 'does not write to the filesystem (except logs),' while also specifying automatic output saves to logs/. Undeclared or under-emphasized local file writes can create privacy and data-retention risks because search terms, URLs, comments, and API-derived data may be persisted unexpectedly on disk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The manifest says the skill uses minimal permissions and 'does not write to the filesystem (except logs),' while also specifying automatic output saves to logs/. Undeclared or under-emphasized local file writes can create privacy and data-retention risks because search terms, URLs, comments, and API-derived data may be persisted unexpectedly on disk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The manifest says the skill uses minimal permissions and 'does not write to the filesystem (except logs),' while also specifying automatic output saves to logs/. Undeclared or under-emphasized local file writes can create privacy and data-retention risks because search terms, URLs, comments, and API-derived data may be persisted unexpectedly on disk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The manifest says the skill uses minimal permissions and 'does not write to the filesystem (except logs),' while also specifying automatic output saves to logs/. Undeclared or under-emphasized local file writes can create privacy and data-retention risks because search terms, URLs, comments, and API-derived data may be persisted unexpectedly on disk.

Content

No source excerpt is available for this finding.

Vague Triggers

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill is configured to trigger on broad research requests even when Douyin is not mentioned, which creates an over-broad invocation surface. That can cause the agent to pull in an external data-collection skill unexpectedly, increasing the chance of unintended network access, token use, and collection of third-party content when the user asked for generic research.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill declares access to an environment variable token (GUAIKEI_API_TOKEN) and network/API use, but the manifest does not explicitly scope or declare those capabilities via permissions/allowed-tools. This weakens reviewability and least-privilege enforcement, making it easier for a skill to access secrets or external services without clear policy boundaries.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

Allowing activation when the task is merely embedded in a multi-step workflow, without tighter constraints, makes the skill more likely to run without informed user intent. In practice this can lead to unnecessary external API calls, token consumption, and collection/storage of platform data during broader tasks that did not clearly request Douyin analysis.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The statement "纯中文界面" indicates a language constraint, but the document does not offer users a language choice or explain why Chinese-only output is required. This can violate language/locale policy expectations for user opt-in or justified locale restrictions.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest explicitly says the skill does not process video publishing or downloading, but this response schema documents video_url as containing both playback and download addresses. That indicates the skill's implemented/outputted data model supports download-related functionality beyond the stated scope.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The schema explicitly documents play_addr as both a playback URL and a video download address, which conflicts with the skill’s stated scope that it does not handle downloads. This can enable downstream agents or integrators to use the skill for media retrieval anyway, undermining policy boundaries and potentially creating compliance, copyright, or data-use risks.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The README explicitly states that scraped Douyin video, account, and comment data is automatically exported to JSON logs, but it does not clearly warn users that this may store potentially sensitive or personal data locally for an indefinite period. In this skill’s context, large-scale collection of comments and competitor data increases privacy and data-handling risk, especially on shared machines or in environments where logs are synced, backed up, or exposed.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The manifest frames this skill as being for tracking热点, competitor research, comment analysis, and hot-topic discovery, and explicitly says it does not handle video publishing or downloading. While this file does not publish or download media, it does perform additional data persistence by writing the retrieved作品结果 to a local file, which goes beyond a purely fetch-and-return workflow implied by the description.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The CLI silently persists fetched Douyin results to a local JSON file without explicit user notice or opt-in. Because comment/post datasets may contain usernames, IDs, or other scraped content, writing them to disk can create unintended data retention and privacy exposure, especially on shared machines or in automated environments.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The CLI persists the full search output to a local JSON file named with user-controlled query data, without any consent prompt, retention control, or indication that potentially sensitive research activity will be stored on disk. In this skill's context, search keywords and returned Douyin content may reveal competitive intelligence, brand monitoring targets, or other sensitive business interests, and local persistence increases exposure to other local users, backups, or log collection agents.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This JavaScript file contains user-facing natural-language strings exclusively in Chinese, including error messages, documentation comments, and generated help output. Under the policy, forcing a specific language without user opt-in or a documented locale 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
95% confidence
Finding

The file contains hard-coded Chinese user-facing status and error messages, such as the validation errors on L07 and L11. Under the policy, forcing a specific language without user opt-in or documented regional 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
94% confidence
Finding

The success and error output strings are also hard-coded in Chinese, which enforces a single language for user-visible interaction. There is no indication in this file of user opt-in, locale negotiation, or a documented region-specific constraint.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The authentication failure string is written only in Chinese and directs users to a WeChat contact, which imposes a specific language and locale expectation without offering a choice. This is a natural-language policy issue because the skill does not provide user opt-in or an alternative language path.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

This code builds and sends GET and POST HTTPS requests using caller-supplied params and data, which may include user or system information, but there is no confirmation prompt or user-facing disclosure around that transmission. For a reusable request utility, the network transmission behavior is not surfaced to the user in logs, prompts, or warnings within this file.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The user-facing strings at L25-L30 are entirely in Chinese, and the file provides no indication that language selection is optional or that the skill is intentionally limited to a Chinese-speaking context. This creates a natural-language locale policy issue because the skill appears to impose a specific language without user opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The title and description fields are written only in Chinese, including parameter descriptions, which indicates a language-specific interface without any stated user opt-in or documented locale restriction. Under the policy, language constraints should either offer choice or be explicitly justified as region-specific.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The schema title and description are written only in Chinese, which can constitute a language/locale policy issue when the skill does not offer an opt-in or document that it is intentionally limited to Chinese-speaking users. The file provides no natural-language indication that this locale restriction is optional or justified as region-specific.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The title and description are written only in Chinese, which imposes a specific language in the skill artifact without offering any language choice or documenting that the schema is intentionally region-specific. This matches the policy category for language or locale constraints expressed in natural-language fields.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

This manifest-format file contains user-facing title and description fields entirely in Chinese, which effectively forces a specific language for users interacting with the schema. The file does not provide an alternative language option or explain that the skill is intentionally limited to a Chinese-speaking context.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

This JSON schema contains natural-language titles and descriptions entirely in Chinese, such as the title and field descriptions. Under the policy rule for language/locale, hard-coding a specific language without opt-in or justification can be a natural-language policy violation.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.