Back to skill

Security audit

guaikei-douyin-raw-to-structured-pipeline

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to do its stated Douyin data-retrieval job, but it handles the API token and saved datasets in ways users should review before installing.

Review this before installing if your Guaikei token is paid, shared, or high-value. Use it only in a private workspace, avoid sensitive monitoring topics, expect keywords and Douyin URLs/IDs to be sent to Guaikei, rotate/restrict the API token where possible, and clean the local logs directory after use.

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:94
Finding

API Credential Transmitted in URL Query Strings

Content
View full analysis

Vulnerability Details

File Locations:

  • src/api/search.js:59-62, 104-107
  • src/api/post.js:23-26, 50-53
  • src/api/comment.js:38-41, 67-70
  • src/api/hot.js:19-22
  • src/utils/request.js:94-120, 123-140

Vulnerability Type: Sensitive credential exposure through URL query parameters
Risk Level: Medium

Vulnerable Code

The API modules add the secret token to a request parameter object. For example, the comment task does so as follows:

js
async function createCommentTask(token, url, limit) {
  const params = {
    _: Date.now(),
    token: token,
  };

  const data = {
    url,
    limit,
  };

  return await requestApi(
    "POST",
    "/api/douyin/comment/url",
    params,
    data,
    constants.CREATE_MAX_ATTEMPTS,
    "创建任务",
  );
}

The shared HTTP client then serializes the parameter object directly into the URL for both POST and GET requests:

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

async function getJson(path, params) {
  if (!path || typeof path !== "string") {
    throw new SkillError("PATH_INVALID", "path 必须是非空字符串");
  }
  if (!params || typeof p
...[truncated 2416 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove token from every query parameter object.
  2. Send the credential in a dedicated request header, preferably:
    js
    headers: {
      Authorization: `Bearer ${token}`,
      "Content-Type": "application/json",
      "Accept-Encoding": "identity",
    }
    
  3. Refactor getJson and postJson to accept the token separately from ordinary request parameters, preventing accidental serialization into the URL.
  4. Configure proxies, gateways, application logs, and telemetry to redact authorization headers and any legacy token query parameter.
  5. Rotate existing API tokens because historical infrastructure logs may already contain them.
  6. Add automated tests asserting that generated request paths never contain token, api_key, secret, or equivalent credential fields.
  7. Ensure error messages and retry logs never include complete request options or authorization values.

T09 · Insecure Skill Coding Practices

Note
Location
src/utils/log.js:5
Finding

Automatic Plaintext Retention of Retrieved Douyin Datasets

Content
View full analysis

Vulnerability Details

File Locations:

  • src/douyin/search-cli.js:258-261
  • src/douyin/comment-cli.js:151-162
  • src/douyin/post-cli.js:152-163
  • src/utils/log.js:5-39

Vulnerability Type: Insecure local storage and excessive retention of retrieved data
Risk Level: Low

Vulnerable Code

The comment workflow serializes the complete response and automatically passes it to the file-writing helper:

js
console.log(JSON.stringify(finalOutput, null, 2));
utils.printSuccess(
  `获取评论任务完成, 共返回 ${finalOutput.results.length} 条结果`,
);

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 same automatic retention pattern is used by the search workflow:

js
await log.taskWrite(
  `${startTime}_${keyword}_${sort}_${time}_${duration}_${content}_search.json`,
  JSON.stringify(finalOutput, null, 2),
);

The shared helper creates a persistent logs directory and writes the content using default filesystem permissions:

js
async function taskWrite(filename, content) {
  if (!filename || typeof filename !== "string") {
    utils.printError("日志文件名必须是非空字符串");
    return;
  }
  if (!content || typeof content !== "string") {
    utils.printError("日志内容必须是非空字符串");
    return;
  }
  let safeFilename = filename
    .replace(/[\\/:*?"<>|]/g, "_")
    .replace(/\.\.+/g, "_")
    .replace(/^\.+|\.+$/g, "");

  if (safeFilename.length > 200) {
    safeFilename = safeFilename.slice(0, 200);
  }
  if (!safeFilename) {
    safeFilename = `log_${Date.now()}`;
  }
  const outputFilename = path.join(
    path.dirname(__filename),
    "..",
    "..",
    "logs",
    safeFilename,
  );

  try {
    await fs.promises.mkdir(path.dirname(outputFilenam
...[truncated 2302 chars]
Remediation
View remediation

Remediation Suggestions

  1. Make local persistence opt-in through an explicit option such as --output or --save.
  2. Do not write files by default when JSON has already been returned through standard output.
  3. Create directories and files with restrictive permissions:
    js
    await fs.promises.mkdir(outputDir, {
      recursive: true,
      mode: 0o700,
    });
    
    await fs.promises.writeFile(outputFilename, content, {
      encoding: "utf8",
      mode: 0o600,
      flag: "wx",
    });
    
  4. Add configurable retention and secure cleanup controls, including a documented command to remove stored results.
  5. Warn users before storing comment datasets containing identifiers or regional metadata.
  6. Allow users to select a secure output directory rather than forcing storage inside the Skill installation.
  7. Exclude logs/ from source control, package publication, CI artifacts, and automatic backups where appropriate.
  8. Document persistence prominently in SKILL.md, not only in secondary documentation.
  9. Consider field minimization or redaction for user identifiers when full raw records are unnecessary.
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 (41)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

A strong description-behavior mismatch exists if the implementation only accesses local filesystem/package metadata rather than Douyin sources. This is dangerous because it can mislead users into providing sensitive inputs or making business decisions based on a tool that does not do what it advertises, which is a trust and integrity failure in the skill supply chain.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

A strong description-behavior mismatch exists if the implementation only accesses local filesystem/package metadata rather than Douyin sources. This is dangerous because it can mislead users into providing sensitive inputs or making business decisions based on a tool that does not do what it advertises, which is a trust and integrity failure in the skill supply chain.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

A strong description-behavior mismatch exists if the implementation only accesses local filesystem/package metadata rather than Douyin sources. This is dangerous because it can mislead users into providing sensitive inputs or making business decisions based on a tool that does not do what it advertises, which is a trust and integrity failure in the skill supply chain.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This markdown file contains user-facing natural-language instructions exclusively in Chinese, including trigger descriptions, usage guidance, and operational notes. Under the policy, forcing a specific language without offering the user a language or locale choice is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The README explains how to use the tool and obtain an API token, but does not clearly disclose that user-entered keywords, URLs, and the resulting platform data are sent to an external guaikei service for processing. This lack of transparent data-flow disclosure is dangerous because users may unknowingly share sensitive research topics, account targets, or monitored content with a third party, creating privacy, compliance, and consent risks.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The natural-language trigger examples are broad enough to match common phrases like '搜索', '找', '热点', or '评论', which can cause the skill to activate in conversations that are not clearly requesting this external Douyin data pipeline. Because the skill can send user-supplied keywords, URLs, and request context to an external service, overbroad triggering creates a real risk of unintended data disclosure and unintended execution.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The intent-recognition rules prioritize very generic activation terms such as '热搜 / 热点 / 榜单 / 今天什么火' and '搜索 / 搜一下 / 找 + 关键词' without sufficiently constraining them to Douyin-specific requests. In an agent environment, this can misroute unrelated user requests into this skill, causing external API calls and disclosure of user prompts, URLs, or inferred interests to the third-party service without clear user intent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The changelog explicitly advertises bulk scraping of an author's published works and retrieval of video comments, but provides no indication of privacy, consent, rate-limit, or platform-terms safeguards. In the context of a skill designed for Douyin search, competitor monitoring, topic discovery, and public-opinion analysis at scale, this omission increases the risk of abusive collection, profiling, or non-compliant use of user-generated content.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
81% confidence
Finding

The CLI sends the provided Douyin URL and limit to external API functions to create and retrieve a comment task. The code does not include a clear user disclosure that supplied content identifiers and request data will be sent to a remote service.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The manifest describes this skill as providing Douyin search, author-work retrieval, comment retrieval, and hot-list querying, which implies fetching and returning data. Here, the CLI additionally writes the full comment results to disk via log.taskWrite, introducing local persistence not stated in the skill purpose and not obviously required to fulfill a one-shot retrieval pipeline.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This code persists the full output, including fetched comments and request metadata, to disk via log.taskWrite(...). Although the file prints progress messages, there is no user-facing disclosure here that execution will create a local artifact containing the retrieved data.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This code contains multiple user-facing strings in Chinese, including status, error, and success messages, but provides no indication that the skill is region-specific or that users can opt into a preferred language. That can violate a language/locale policy when a skill implicitly forces one language for all users.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The CLI persists the full fetched Douyin post results to a local JSON file after completing the request. This creates an undeclared secondary data sink on disk, which can expose scraped content, metadata, and query targets to other local users, backup systems, or later processes, especially because there is no consent prompt, retention control, or indication of where files are stored.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The code silently writes fetched results to a local JSON file without any user-facing warning or opt-in in this file. In the context of a data-retrieval skill, this increases privacy and data-handling risk because users may reasonably expect transient retrieval/output, not background local retention of potentially sensitive collection results.

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 named with the user-supplied keyword, creating persistent storage of potentially sensitive search terms and returned data without explicit opt-in or retention controls. In multi-user systems, shared workspaces, CI runners, or synced directories, this can unintentionally expose user activity, collected content, or business research data beyond the immediate execution context.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This code embeds user-facing error text in Chinese, such as "请求失败", with no indication that users can choose another language or that the skill is intentionally limited to a Chinese-speaking context. The policy explicitly disallows forcing a specific language without user opt-in or clear justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The authentication error shown to users is entirely in Chinese and includes support instructions, with no opt-in or locale negotiation. This is a natural-language policy violation because it forces a specific language for a user-facing message.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The file’s comments and all user-facing error/result strings are written exclusively in Chinese, including validation errors and formatted output. Under the stated 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

Low
Category
Not specified by scanner
Confidence
96% confidence
Finding

This manifest-style JSON file contains user-facing title and description fields entirely in Chinese, including parameter descriptions. Under the policy, forcing a specific language without user opt-in can be a natural-language policy violation, and this file does not indicate that the skill is intentionally limited to a Chinese-speaking or region-specific audience.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The title and description force a specific language/locale in natural-language schema metadata, and the file does not indicate that Chinese is optional or that the skill is intended only for Chinese-speaking users. This can violate language-choice policy when the skill is used in broader contexts.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

The schema title and multiple description fields are written entirely in Chinese, which imposes a specific language in natural-language metadata. There is no indication that the skill is region-specific or that users can opt into this locale, so this may violate language/locale policy guidance.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

This JSON schema uses Chinese-only natural-language title and description fields for the skill and its parameters. Because the file does not indicate that the skill is region-specific or offer any language/locale choice, it presents a potential language-policy issue under the rule for forced locale or language without opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

This JSON manifest/schema file contains user-facing title and description text only in Chinese. Because the file does not indicate that the skill is intentionally region-specific or provide any language/locale opt-in, it can violate the policy against forcing a specific language without user choice.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

This manifest file contains all human-readable titles and descriptions in Chinese, but it does not state that the skill is region-specific or that users may choose another language. Under the policy rule, forcing a specific language without opt-in or documented justification is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.