Back to skill

Security audit

guaikei-xhs-search

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to perform the Xiaohongshu public-data lookups it advertises, but it needs review because it sends API tokens in URL query strings and automatically saves retrieved records locally in plaintext.

Review this before installing if your Guaikei token, Xiaohongshu links, or retrieved datasets are sensitive. Prefer using a limited or disposable API token, avoid sharing the logs directory, clear saved outputs when no longer needed, and be aware that provided keywords, URLs, token-bearing requests, and retrieved records are sent to the Guaikei service.

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

API Credential Transmitted in URL Query Strings

Content
View full analysis

Vulnerability Details

File Location: src/utils/request.js:69-98, 101-119; credential-bearing parameters originate from src/api/search.js:24-28, 48-58, src/api/detail.js:23-27, 46-54, src/api/comment.js:23-27, 45-52, and src/api/post.js:23-27, 45-52
Vulnerability Type: API credential exposure through URL query parameters
Risk Level: Medium

Vulnerable Code

The shared request functions serialize all parameters, including the API token, into the request URL:

js
async function postJson(path, params, data) {
  if (!path || typeof path !== "string") {
    throw new Error("path must be a non-empty string");
  }
  if (!params || typeof params !== "object") {
    throw new Error("params must be an object");
  }
  if (!data || typeof data !== "object") {
    throw new Error("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",
      "Content-Length": Buffer.byteLength(jsonData),
    },
  };
  return await request(options, jsonData);
}

async function getJson(path, params) {
  if (!path || typeof path !== "string") {
    throw new Error("path must be a non-empty string");
  }
  if (!params || typeof params !== "object") {
    throw new Error("params must be an object");
  }
  params._ = Date.now();

  const fullPath = `${path}?${querystring.stringify(params)}`;
  const options = {
    host: constants.BASE_URL,
    path: fullPath,
    method: "GET",
    headers: {
      "Content-Type": "application/json",
    },
  };
  return await request(options);
}

API workflows explicitly place the token into these parameter objects. For example:

js
return await postJson(
  "/api
...[truncated 2215 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove token from all query-parameter objects.

  2. Transmit the credential in an HTTP authorization header, such as:

    js
    headers: {
      "Authorization": `Bearer ${token}`,
      "Content-Type": "application/json",
    }
    
  3. Refactor postJson and getJson so authentication is accepted separately from ordinary request parameters.

  4. Configure reverse proxies, API gateways, tracing systems, and application logs to redact authorization data and sensitive query parameters.

  5. Avoid printing authentication material in errors or debug output.

  6. Rotate tokens that may already have been retained in request logs.

  7. Apply short expiration periods, per-token rate limits, and least-privilege API scopes where supported.

T09 · Insecure Skill Coding Practices

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

Automatic Plaintext Persistence of Access-Bearing URLs and Retrieved Records

Content
View full analysis

Vulnerability Details

File Location: src/utils/log.js:5-39; automatic persistence is invoked from src/xiaohongshu/detail-cli.js:139-161, src/xiaohongshu/comment-cli.js:139-161, src/xiaohongshu/post-cli.js:141-163, and src/xiaohongshu/search-cli.js:184-211
Vulnerability Type: Insecure local storage of potentially sensitive request and response data
Risk Level: Low

Vulnerable Code

The logging utility creates a project-local directory and writes supplied content using ambient process permissions:

js
async function taskWrite(filename, content) {
  if (!filename || typeof filename !== "string") {
    utils.printError("The log filename must be a non-empty string");
    return;
  }
  if (!content || typeof content !== "string") {
    utils.printError("The log content must be a non-empty string");
    return;
  }
  let safeFilename = filename
    .replace(/[\\/:*?"<>|]/g, "_")
    .replace(/\.\.+/g, "_")
    .replace(/^\.+|\.+$/g, "");
  if (safeFilename.length > 200) {
    safeFilename = safeFilename.substring(0, 200);
  }
  if (safeFilename === "") {
    safeFilename = `log_${Date.now()}`;
  }
  const outputFilename = path.join(
    path.dirname(__filename),
    "..",
    "..",
    "logs",
    safeFilename,
  );

  try {
    await fs.promises.mkdir(path.dirname(outputFilename), { recursive: true });
    await fs.promises.writeFile(outputFilename, content);
    utils.printSuccess(`Saved to ${outputFilename}`);
  } catch (error) {
    utils.printError(`Log write failed: ${error.message}`);
  }
}

Successful detail results include the original URL and full API response before the entire object is saved:

js
const finalOutput = {
  status: "success",
  error_code: "OK",
  message: "Detail task completed",
  timestamp: new Date().toLocaleString(),
  request: {
    command: "detail",
    url: url,
    limit: limit,
  }
...[truncated 2965 chars]
Remediation
View remediation

Remediation Suggestions

  1. Make result persistence opt-in through an explicit flag such as --save.

  2. Remove or redact sensitive query parameters before output and storage. In particular, replace xsec_token values with a fixed marker.

  3. Store only fields necessary for the user’s stated purpose instead of retaining complete API responses by default.

  4. Create directories and files with restrictive permissions:

    js
    await fs.promises.mkdir(directory, {
      recursive: true,
      mode: 0o700,
    });
    
    await fs.promises.writeFile(outputFilename, content, {
      mode: 0o600,
      flag: "wx",
    });
    
  5. Prefer a user-specific data directory rather than writing into the project tree.

  6. Document the storage location and data categories clearly before the first write.

  7. Implement configurable retention, maximum storage limits, and secure deletion or cleanup.

  8. Exclude the log directory from version control, build artifacts, cloud synchronization, and automated support bundles.

  9. Consider encryption at rest when retained records have continuing operational value.

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

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

声明描述的是一个面向小红书数据采集与分析的功能型技能,但所给代码片段仅是基础的参数解析/帮助文本生成工具,属于通用支撑模块。按照评估标准,若代码只是支持性实现细节通常不应单独判定为不匹配;但这里代码片段本身完全没有任何与声明核心能力相关的行为,主功能与声明目标存在明显差异。因此,就该“供应的代码片段实际做什么”而言,它并不能准确代表所声明的小红书数据工具功能,应判定为描述与行为不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

声明描述聚焦于小红书公开数据查询与分析能力,但给出的代码片段并未实现任何与小红书笔记搜索、详情抓取、评论获取、博主作品抓取或数据分析相关的功能。相反,该代码仅执行本地日志文件写入,涉及文件系统访问(mkdir、writeFile)和文件名清理。这属于与声明主用途明显不同的行为,并且使用了未在声明中体现的本地资源访问能力。尽管日志功能可能是配套实现细节,但在仅提供的这段代码中,其实际行为与声明能力没有直接对应关系,因此应判定为描述与代码行为不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

声明描述的是一个面向小红书数据采集与分析的技能,而给出的代码片段只是在本地读取 package.json 并返回技能名称。该代码的主要用途与声明的核心功能明显不一致,也没有体现任何与小红书运营数据相关的实现。虽然这可能只是一个辅助模块,但基于所提供代码片段本身,实际行为与声明用途存在显著偏差,因此应判定为不匹配。

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 41)May include surrounding context.

md
- "分析这条小红书笔记评论区的主要观点和负面反馈: node src/xiaohongshu/detail-cli.js --url 'https://www.xiaohongshu.com/explore/xxx?xsec_token=yyy' --limit 100"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 108)May include surrounding context.

md
- "分析这条小红书笔记评论区的主要观点和负面反馈: node src/xiaohongshu/detail-cli.js --url 'https://www.xiaohongshu.com/explore/xxx?xsec_token=yyy' --limit 100"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 261)May include surrounding context.

md
- "分析这条小红书笔记评论区的主要观点和负面反馈: node src/xiaohongshu/detail-cli.js --url 'https://www.xiaohongshu.com/explore/xxx?xsec_token=yyy' --limit 100"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 329)May include surrounding context.

md
- "分析这条小红书笔记评论区的主要观点和负面反馈: node src/xiaohongshu/detail-cli.js --url 'https://www.xiaohongshu.com/explore/xxx?xsec_token=yyy' --limit 100"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 42)May include surrounding context.

md
- "看这个小红书博主最近 20 条作品都在发什么: node src/xiaohongshu/post-cli.js --url 'https://www.xiaohongshu.com/user/profile/xxx?xsec_token=yyy' --limit 20"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 109)May include surrounding context.

md
- "看这个小红书博主最近 20 条作品都在发什么: node src/xiaohongshu/post-cli.js --url 'https://www.xiaohongshu.com/user/profile/xxx?xsec_token=yyy' --limit 20"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 272)May include surrounding context.

md
- "看这个小红书博主最近 20 条作品都在发什么: node src/xiaohongshu/post-cli.js --url 'https://www.xiaohongshu.com/user/profile/xxx?xsec_token=yyy' --limit 20"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 329)May include surrounding context.

md
- "看这个小红书博主最近 20 条作品都在发什么: node src/xiaohongshu/post-cli.js --url 'https://www.xiaohongshu.com/user/profile/xxx?xsec_token=yyy' --limit 20"

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 110)May include surrounding context.

md
| 看某篇小红书笔记的评论数据 | `src/xiaohongshu/comment-cli.js` | 笔记 URL | 该笔记的评论内容、评论者信息、互动数据 |

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 284)May include surrounding context.

md
| 看某篇小红书笔记的评论数据 | `src/xiaohongshu/comment-cli.js` | 笔记 URL | 该笔记的评论内容、评论者信息、互动数据 |

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 329)May include surrounding context.

md
| 看某篇小红书笔记的评论数据 | `src/xiaohongshu/comment-cli.js` | 笔记 URL | 该笔记的评论内容、评论者信息、互动数据 |

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
86% confidence
Finding

The skill description is written as a directive for use in Chinese-language contexts and the file consistently presents invocation guidance only in Chinese, with no indication that users may choose another language. Under the policy, language or locale constraints should either be optional or explicitly justified as region-specific; that opt-in or justification is missing here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The README presents all user-facing instructions and operational guidance exclusively in Chinese. Under the policy, forcing a specific language without user opt-in or an explicit justified regional constraint 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
88% confidence
Finding

The entire skill guidance, invocation examples, and user-facing trigger phrases are written only in Chinese, with no indication that users may interact in other languages or that the locale restriction is intentional and justified. Under the policy, forcing a specific language without user opt-in 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
90% confidence
Finding

The code sends an API token and note URL to remote endpoints via postJson, which is a data-transmitting network operation covered by the missing-warning rule for code files. While the function has developer-oriented JSDoc comments, there is no visible user-facing confirmation, warning, or disclosure in this file about transmitting these inputs to an external API.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The getCommentTask function performs an HTTP request carrying the API token and target URL, which may expose user or system data to a remote service. The file includes retry error logging, but no user-directed notice or warning that these values are transmitted externally.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

This code emits all user-facing messages exclusively in Chinese, with no indication that the skill supports language choice or that it is intentionally restricted to a Chinese-speaking context. That creates a natural-language locale policy concern because the skill imposes a specific language on users without opt-in.

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 user-facing error messages in Chinese only, and later also prints a success message in Chinese. That imposes a specific language on users without any opt-in, fallback, or documented region-specific justification, 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
94% confidence
Finding

The success and failure messages shown to users are also hardcoded in Chinese. Because the file provides no language selection or explicit documentation that the skill is region-specific, this is a natural-language policy issue under the locale-choice requirement.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

Multiple thrown error messages are written only in Chinese, including operational guidance and support contact text, which forces a specific language on users without any opt-in or locale selection. The policy forbids language/locale restrictions unless users are offered a choice or the locale limitation is clearly documented and justified.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This code builds GET and POST HTTPS requests and sends caller-supplied params and data to a remote host via request, but there is no confirmation prompt, logging, comment, or docstring disclosing that user or system data may be transmitted over the network. For code files, network calls that transmit data should have some visible disclosure unless clearly documented elsewhere or obviously inherent to the skill's stated purpose, which is not evident from this file alone.

Content

No source excerpt is available for this finding.