Back to skill

Security audit

douyin-public-data-fetcher-guaikei

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly performs advertised Douyin public-data lookups, but it has review-worthy issues around contradictory contact/promotional auth output and exposed API-token handling.

Review before installing. Use a dedicated, revocable GUAIKEI_API_TOKEN, expect Douyin queries and URLs to be sent to www.guaikei.com, and expect result logs to be saved locally. Avoid shared machines or repositories for generated logs, and rotate the token if it may have appeared in URL logs.

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

Contradictory Runtime Promotion and Contact Injection in Authentication Errors

Content
View full analysis

Vulnerability Details

File Location: src/utils/token.js:23-32, src/utils/request.js:49-56, src/douyin/search-cli.js:169-188
Vulnerability Type: Runtime output manipulation and instruction-policy contradiction
Risk Level: High

Complete Code Snippets

From src/utils/token.js:23-32:

js
function skillToken(token) {
  if (!isValidToken(token)) {
    utils.printWarn("Warning: GUAIKEI_API_TOKEN is not configured correctly; the skill has been suspended.");
    utils.printSuccess("\tQuick access channel: www.guaikei.com");
    return "";
  }

  utils.printInfo("The configured private token is in use");
  return token;
}

From src/utils/request.js:49-56:

js
} else if (res.statusCode === 401 || res.statusCode === 403) {
  const e = new AuthError(
    "GUAIKEI_API_TOKEN is invalid. Check the environment variable or contact WeChat/phone number 13395823479 for assistance.",
  );
  e.noRetry = true;
  reject(e);
} else {

From src/douyin/search-cli.js:169-188:

js
} catch (error) {
  utils.printError(`Search failed: ${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,
    },

Technical Analysis

SKILL.md states that invalid-token handling must produce only a neutral error, and it expressly prohibits runtime website links, contact details, or promotional language. The implementation violates those declared constraints in two separate authentication paths:

  1. A locally missing or malformed token causes the runtime to advertise www.guaikei.com.
  2. An HTTP 401 or 403 response produces a hardcoded message containing an external WeCha ...[truncated 2103 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove the website, phone number, WeChat reference, and all acquisition or promotional language from runtime code.
  2. Return a fixed neutral result, such as:
    json
    {
      "status": "error",
      "error_code": "AUTH_REQUIRED",
      "message": "GUAIKEI_API_TOKEN is missing or invalid."
    }
    
  3. Do not propagate raw exception or server-provided messages directly into Agent-facing JSON. Map internal errors to an allowlisted set of neutral public messages.
  4. Keep token-acquisition instructions exclusively in user documentation, consistent with SKILL.md.
  5. Add automated tests for malformed tokens and HTTP 401/403 responses. Tests should reject output containing URLs, phone numbers, contact methods, payment language, or marketing text.
  6. Ensure all four CLI commands use the same centralized, neutral authentication-error formatter.

T09 · Insecure Skill Coding Practices

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

API Credential Exposed in URL Query Parameters

Content
View full analysis

Vulnerability Details

File Location: src/api/search.js:59-79, src/api/search.js:104-124, src/utils/request.js:94-120, src/utils/request.js:123-140
Vulnerability Type: Sensitive credential transmitted in request URLs
Risk Level: Medium

Complete Code Snippets

From src/api/search.js:59-79:

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

const data = {
  keyword,
  sort_type: sort,
  publish_time: time,
  filter_duration: duration,
  content_type: content,
  limit: limit,
};

return await requestApi(
  "POST",
  "/api/douyin/general-search/keyword",
  params,
  data,
  constants.CREATE_MAX_ATTEMPTS,
  "Create task",
);

From src/api/search.js:104-124:

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,
  "Query task",
);

From src/utils/request.js:94-120:

js
async function postJson(path, params, data) {
  if (!path || typeof path !== "string") {
    throw new SkillError("PATH_INVALID", "path must be a non-empty string");
  }
  if (!params || typeof params !== "object") {
    throw new SkillError("PARAM_INVALID", "params must be an object");
  }
  if (!data || typeof data !== "object") {
    throw new SkillError("DATA_INVALID", "data must be an object");
  }
  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": Bu
...[truncated 3509 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove token from every query-parameter object.
  2. Transmit the credential in an authorization header:
    js
    headers: {
      Authorization: `Bearer ${token}`,
      "Content-Type": "application/json",
      "Accept-Encoding": "identity",
    }
    
  3. Refactor requestApi(), postJson(), and getJson() so authentication is a dedicated argument rather than ordinary request data.
  4. Ensure request logging and telemetry redact Authorization, cookies, tokens, and other secret-bearing headers.
  5. Avoid including credentials in exception messages, request paths, debugging output, or persisted logs.
  6. Rotate all tokens that may already have been recorded in URL logs.
  7. Configure server, proxy, and monitoring retention policies to remove historical URLs containing the token parameter.
  8. Add tests that intercept outgoing requests and assert that request URLs never contain token, api_key, or equivalent credential parameters.
  9. Apply the change consistently to search, comment, post, and hot endpoints, including repeated polling requests.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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 (46)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Another independently reported mismatch indicates the implementation accesses local package metadata and lacks the advertised Douyin retrieval features. This makes the skill materially misleading: users may think they are invoking a narrowly scoped data-fetcher when the code is actually doing unrelated local operations.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Another independently reported mismatch indicates the implementation accesses local package metadata and lacks the advertised Douyin retrieval features. This makes the skill materially misleading: users may think they are invoking a narrowly scoped data-fetcher when the code is actually doing unrelated local operations.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Another independently reported mismatch indicates the implementation accesses local package metadata and lacks the advertised Douyin retrieval features. This makes the skill materially misleading: users may think they are invoking a narrowly scoped data-fetcher when the code is actually doing unrelated local operations.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
80% confidence
Finding

The skill explicitly depends on an environment variable token (GUAIKEI_API_TOKEN) and invokes Node.js commands, but it does not declare a corresponding tool/permission scope. Undeclared access to environment data weakens reviewability and can cause the agent runtime to grant broader capabilities than users or auditors expect.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill says it should be used even when the user does not mention Douyin, which broadens activation beyond clear user intent. Over-broad routing can cause the agent to invoke a data-fetching skill in unrelated contexts, increasing the chance of unnecessary external requests, token use, or unintended data handling.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The invocation guidance repeats that the skill should trigger even without the user saying 'Douyin', creating ambiguous platform selection. In context, this is more dangerous because the skill requires an API token and may perform networked data collection, so accidental invocation has real side effects and cost.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This JSON schema uses Chinese-only natural-language titles and descriptions throughout, such as the title and property descriptions, which imposes a specific language/locale in the skill metadata. The file does not indicate that Chinese is optional, user-selected, or justified as a region-specific tool, so it conflicts with the language/locale policy requirement.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
76% confidence
Finding

The manifest states the skill is not applicable to downloading content, but this response schema explicitly defines video_url as containing both playback and download addresses. Even though this is only a schema file, it indicates the skill returns downloadable video URLs, which extends beyond the stated read/search/research-oriented purpose.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This JSON schema contains user-facing natural-language strings such as the title and descriptions entirely in Chinese. Because the file does not document that the skill is region-specific or offer a language/locale choice, it appears to enforce a specific language without user opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The README is written entirely in Chinese and the natural-language command mappings and intent rules are all defined using Chinese trigger phrases. Because the document does not offer an alternative language or state that the skill is intentionally limited to Chinese-language Douyin use cases, it may violate a language/locale policy requiring user choice or documented justification.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The README states that scraped Douyin data is automatically exported to local JSON log files, including search results, account works, and comments, but it does not prominently warn users that these files may contain personal or sensitive public data and can persist on disk beyond the immediate task. In a scraping and analytics skill, silent retention increases the risk of unintended disclosure through shared machines, backups, source control commits, or later reuse outside the original purpose.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The changelog and feature descriptions are written entirely in Chinese, and the file does not indicate that the skill is region-specific or that users may choose another language. Under the policy, forcing a specific language without opt-in can be 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 entire skill documentation, parameter descriptions, and usage examples are written in Chinese, with no indication that users may choose another language or locale. This creates a natural-language locale constraint that is not presented as optional or justified as region-specific compliance guidance.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This file uses Chinese-only natural-language comments and parameter descriptions throughout, which can impose a specific language/locale on maintainers or operators without any documented opt-in. The policy explicitly calls for flagging language or locale constraints when they are forced and not justified as region-specific.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The CLI persists fetched Douyin comment data to a local JSON file even though its stated purpose is only to retrieve and display public data. Comments can still contain personal data, sensitive opinions, or account-linked identifiers, and silently retaining them on disk increases exposure through later theft, accidental sharing, or misuse. In this skill context, bulk comment collection makes the persistence more concerning because it enables durable local datasets beyond the immediate fetch operation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The tool saves comment results locally without any user-facing warning, confirmation, or explicit output-path selection. This creates a privacy and data-handling issue because operators may believe the tool only performs transient retrieval, while it actually leaves a persistent artifact containing harvested comments that could be exposed to other local users, backups, or downstream processes. Given this skill’s purpose of scraping public comments at scale, undisclosed persistence materially increases the risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

This code reads a credential from process.env.GUAIKEI_API_TOKEN and then uses it to create and fetch a remote task, which implies transmission of user-supplied data (url, limit) to an external service. While the code logs progress, it does not clearly disclose to the user that a token is being used and that the supplied Douyin URL is sent to a remote API.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The CLI persists fetched Douyin results to a local JSON file after completing the user-requested fetch. While logging may be operationally useful, the skill description only frames this as search/fetch/query functionality and does not disclose local retention, so users may unknowingly leave potentially sensitive research data, account lists, or comment-derived information on disk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The code accesses process.env.GUAIKEI_API_TOKEN and then sends authenticated requests through search.createSearchTask, implying network transmission using sensitive credentials. While network use is part of a search tool's purpose, this file does not clearly warn the user that an environment-stored token is required and will be used for external API calls.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The CLI writes the full search output to a local JSON file whose name includes the user's keyword. Search results and queries can contain sensitive research topics or personal-interest data, and persisting them without explicit consent or a retention policy creates a privacy leak to other local users, backups, or log collectors. In this skill's context, content research and comment/keyword analysis make such data persistence more sensitive, not less.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Several user-facing error strings in this file are written only in Chinese, such as the request failure messages, which forces a specific language for runtime output. The policy allows locale constraints only when documented and justified or when users are given a choice, neither of which is present here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The AuthError message is user-facing and entirely in Chinese, requiring a specific language for a critical failure condition. There is no indication of user opt-in, fallback localization, or documented region-specific scope.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

This manifest/config file contains user-facing title and description fields entirely in Chinese, which effectively forces a specific language for users consuming the schema metadata. The file does not indicate that the skill is region-specific or provide any opt-in or alternative locale, which matches the language/locale policy concern.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

The schema uses Chinese-only natural-language strings for the title, description, and field descriptions, which imposes a specific language on consumers of the skill metadata. There is no indication that the skill is intentionally China-specific or that users can opt into this locale.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

This JSON schema contains natural-language title and description fields exclusively in Chinese, including the top-level metadata and property descriptions. Because the file does not document that the skill is China-specific or offer any language/locale choice, it may conflict with a policy requiring user opt-in before forcing a specific language.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.