Back to skill

Security audit

guaikei-douyin-comprehensive-feed-grabber

Security checks for vulnerabilities and agentic risk

Overview

This Douyin data-collection skill mostly matches its stated purpose, but it has review-worthy issues around credential handling, broad activation, local result retention, and contradicted runtime messaging.

Review this skill before installing. It is designed for public Douyin research and does not show destructive behavior or local privilege escalation, but it sends a reusable API token in URLs, saves fetched results locally by default, may activate on broad research prompts, and can display promotional contact details during authentication failures despite saying it will not.

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/request.js:51
Finding

Undeclared Promotional Contact Injected into Authentication Error Output

Content
View full analysis

Vulnerability Details

File Location: src/utils/request.js:51-55, propagated by src/douyin/search-cli.js:170-198 and equivalent error handlers in the comment, post, and hot CLIs
Vulnerability Type: Runtime output manipulation and instruction-policy violation
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 error is then copied into both diagnostic output 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 request implementation hard-codes an external WeChat contact in the error generated for HTTP 401 and 403 responses. CLI handlers subsequently include the message in stderr and in the JSON written to stdout.

This behavior directly contradicts the token-management policy in SKILL.md:36-38, which requires authentication failures to use neutral wording and explicitly prohibits runtime contact details, website links, or promotional content. Because stdout is documented as machine-readable JSON, ...[truncated 1556 chars]

Remediation
View remediation

Remediation Suggestions

  1. Replace the authentication error with a neutral message, for example:

    js
    const e = new AuthError(
      "GUAIKEI_API_TOKEN is invalid or expired. Check the configured environment variable.",
    );
    
  2. Remove all contact details, marketing language, and support links from runtime messages.

  3. Centralize authentication-error formatting so every CLI returns the same neutral response.

  4. Avoid directly exposing arbitrary upstream error text to agent-visible output. Map remote errors to a documented set of local error codes and messages.

  5. Add automated tests that simulate HTTP 401 and 403 responses and assert that stdout and stderr contain no phone numbers, social-media contacts, URLs, or promotional language.

  6. Review equivalent catch paths in:

    • src/douyin/search-cli.js
    • src/douyin/post-cli.js
    • src/douyin/comment-cli.js
    • src/douyin/hot-cli.js

T09 · Insecure Skill Coding Practices

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

API Authentication Token Transmitted in URL Query Parameters

Content
View full analysis

Vulnerability Details

File Location: src/api/search.js:59-62 and src/utils/request.js:94-119; the same pattern is used by the comment, post, and hot API modules
Vulnerability Type: Sensitive credential exposure through URL query strings
Risk Level: Medium

Vulnerable Code

The API modules place the token in a query-parameter object:

js
async function createSearchTask(
  token,
  keyword,
  sort,
  time,
  duration,
  content,
  limit,
) {
  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,
    "创建任务",
  );
}

The shared request utility serializes the token into the request URL:

js
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 GET implementation uses the same URL construction:

js
const fullPath = `${path}?${querystring.stringify(params)}`;

...[truncated 2449 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove token from every query-parameter object.

  2. Send the credential in a dedicated authorization header, preferably:

    js
    headers: {
      Authorization: `Bearer ${token}`,
      "Content-Type": "application/json",
      "Accept-Encoding": "identity",
      "Content-Length": Buffer.byteLength(jsonData),
    }
    
  3. Refactor postJson() and getJson() to receive authentication separately from ordinary query parameters.

  4. Ensure request and error logging redacts authorization headers and never logs token values.

  5. Configure API gateways, reverse proxies, web servers, and tracing platforms to redact existing token query parameters during migration.

  6. Rotate tokens that may previously have appeared in URL or access logs.

  7. Establish short token lifetimes and revocation support to reduce the impact of future disclosure.

  8. Add tests that inspect generated request paths and fail if sensitive parameter names such as token, secret, or api_key are present.

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

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill claims minimal side effects, but it explicitly states that output files are automatically saved under logs/ with timestamps and query parameters. Automatic filesystem writes can leak sensitive user queries, URLs, or operational metadata to disk, and the mismatch makes that data retention easier to overlook during review.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill claims minimal side effects, but it explicitly states that output files are automatically saved under logs/ with timestamps and query parameters. Automatic filesystem writes can leak sensitive user queries, URLs, or operational metadata to disk, and the mismatch makes that data retention easier to overlook during review.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill claims minimal side effects, but it explicitly states that output files are automatically saved under logs/ with timestamps and query parameters. Automatic filesystem writes can leak sensitive user queries, URLs, or operational metadata to disk, and the mismatch makes that data retention easier to overlook during review.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
86% confidence
Finding

The skill declares access to an environment variable (GUAIKEI_API_TOKEN) and directs command execution, but it does not declare an explicit tool scope such as allowed tools or permissions. In an agent setting, missing scope boundaries can cause the runtime to grant broader-than-necessary capabilities, increasing the chance of unintended secret access or command execution outside the intended workflow.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The generalized trigger allows activation even when the user did not mention Douyin, which can cause the agent to invoke external data collection against a platform the user did not intend. In a multi-skill environment, overbroad triggering can lead to unnecessary external requests, privacy surprises, and use of a token-backed service without clear user consent.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

Generic trigger phrases like '热点' or '榜单' are ambiguous and may match unrelated tasks, causing accidental invocation of this skill. Because the skill performs networked lookups using a tokenized external service, misrouting user intent can expose queries to the wrong provider and produce unrequested data collection.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The title and descriptions are presented entirely in Chinese, which can amount to a language-policy issue if the skill is expected to be usable without forcing a specific language on users. There is no indication that Chinese is optional, user-selected, or justified by a documented region-specific scope.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The title and multiple description fields force a specific language/locale in the schema's natural-language metadata. Under the policy, locale-specific language should either be optional for users or clearly documented as a justified regional constraint, which is not present here.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The schema explicitly documents video_url as containing both playback and download addresses, which contradicts the skill's stated limitation that it is not for downloading videos. In this context, that mismatch can enable downstream agents or integrators to use the skill for prohibited media retrieval, expanding abuse risk and creating policy/compliance exposure.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This JSON schema contains human-readable title and description strings exclusively in Chinese, which imposes a specific language on users and integrators. The file does not document that the schema is intended only for a Chinese-language audience or provide any language/locale choice, which matches the stated language/locale policy concern.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The manifest explicitly states the skill is not for downloading videos, but this response schema describes play_addr as both a playback address and a '视频下载地址' (video download address). That indicates the skill's documented data model supports a downloading-oriented capability outside the stated scope.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This file contains natural-language strings such as comments and operation labels like '创建任务' and '查询任务' that assume a Chinese-speaking user or operator. The policy only permits fixed language behavior when there is explicit user opt-in or a justified locale constraint, neither of which appears in this file.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The manifest frames the skill as something to use when a user wants to search and inspect public Douyin data, and explicitly narrows scope around data access use cases. In this file, after fetching comments, the code persists the full output to disk via log.taskWrite, which is a state-changing side effect not conveyed by the manifest's read-oriented description.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This code file contains multiple user-facing strings exclusively in Chinese, including status messages and errors. Under the policy rule, forcing a specific language without user opt-in is a natural-language policy violation unless the locale restriction is clearly documented and justified, which is not evident in this file.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

This CLI writes the full fetched results to a local JSON file automatically after successful execution, without any explicit warning, consent prompt, or opt-in flag. Because the tool is designed to collect public Douyin data but may include comments, profile/work metadata, and potentially sensitive research datasets, silent local persistence increases the risk of unintended retention, later disclosure, or collection in shared environments.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The CLI writes full search results to a local JSON log file without explicit user notice or consent, creating an unexpected persistence channel on disk. Even if the source data is public, the queried keywords, result set, and timestamps can reveal user interests, research topics, or operational context, and may be accessible to other local users, backup systems, or later processes.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code emits all visible error strings in Chinese, and later also prints a Chinese success message. For a general utility file, that constitutes a natural-language locale policy concern because the skill does not offer language selection or document that it is intentionally Chinese-only.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The success and failure messages shown to the user are hard-coded in Chinese. Because no language choice, opt-in, or documented regional justification appears in this file, the skill may violate organizational language/locale policy.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The authentication error string is hard-coded entirely in Chinese and directs the user to take follow-up action in that language. This imposes a specific language on users without any apparent opt-in or locale selection, which matches the language/locale policy violation criteria.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This code emits all user-facing status and warning messages in Chinese, including the token misconfiguration warning and success/info output. Because the file does not offer any user opt-in, fallback language, or documented region-specific justification, it creates a natural-language locale policy issue under the language-choice rule.

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’s docstrings and all user-facing error/output strings are written in Chinese, indicating the skill enforces a specific language for interaction. Under the policy, a fixed language without user opt-in or documented regional justification is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The generated result message uses Chinese labels such as result title, publisher, publish time, links, and counts, with no mechanism to choose another language. This is a user-visible language constraint and qualifies as a policy violation absent explicit opt-in or documented justification.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The file explicitly states that invalid-token handling must emit only neutral errors and must not print contact information or promotional links. However, this file is purely documentation/manifest content and contains no executable logic implementing or enforcing that guarantee, so the documented operational constraint is unsupported by the actual file contents.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The file states “纯中文界面”, which imposes a language constraint. Under the policy, forcing a specific language without user opt-in is a natural-language policy concern unless the locale restriction is explicitly justified as region-specific or optional.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

This JSON manifest/schema uses broad descriptive text about fetching Douyin comments but provides no explicit activation conditions, constraints, or exclusion cases. For manifest-type files, the absence of specific trigger scope can make invocation behavior ambiguous in systems that rely on descriptive metadata.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.