Back to skill

Security audit

红笔记数据收割

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real Xiaohongshu data tool, but it needs Review because it handles an API token unsafely and automatically saves collected results locally.

Install only if you are comfortable sending Xiaohongshu keywords, links, limits, and your Guaikei API token to www.guaikei.com. Treat GUAIKEI_API_TOKEN as a secret, monitor or rotate it if exposed, and review/delete the generated logs because complete collected results are saved locally by default.

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

API Token Exposed in URL Query Parameters

Content
View full analysis

Vulnerability Details

File Location: src/utils/request.js:76-119; token-bearing calls originate from src/api/search.js:23-26, 52-55, src/api/comment.js:20-23, 46-49, src/api/detail.js:20-23, 46-49, and src/api/post.js:20-23, 46-49
Vulnerability Type: Authentication secret exposure through URL query strings
Risk Level: Medium

Vulnerable Code

javascript
async function postJson(path, params, data) {
  if (!path || typeof path !== "string") {
    throw new Error("path 必须是非空字符串");
  }
  if (!params || typeof params !== "object") {
    throw new Error("params 必须是对象");
  }
  if (!data || typeof data !== "object") {
    throw new Error("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",
      "Content-Length": Buffer.byteLength(jsonData),
    },
  };
  return await request(options, jsonData);
}

async function getJson(path, params) {
  if (!path || typeof path !== "string") {
    throw new Error("path 必须是非空字符串");
  }
  if (!params || typeof params !== "object") {
    throw new Error("params 必须是对象");
  }
  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);
}

Representative token-bearing API call from src/api/search.js:23-26:

javascript
return await postJson(
  "/api/xiaohongshu/note-search/keyword",
  { _: Date.now(), token: token },
  { keyword, type, sort, time, limit },
);

Representative token-bearing query request from src/api/search.js:52-55:

javascript
const res = await getJson("/api/xiaohongshu/note-search/info", {
  _: Date.now()
...[truncated 1806 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove the token from all query parameter objects.
  2. Transmit it in an authentication header, for example:
javascript
headers: {
  "Authorization": `Bearer ${token}`,
  "Content-Type": "application/json"
}
  1. Change postJson and getJson to accept authentication separately from ordinary query parameters.
  2. Ensure server, proxy, telemetry, and error logs redact Authorization and any legacy token parameters.
  3. Rotate tokens that may already have appeared in access logs.
  4. Review and purge historical request logs according to the service's credential-retention policy.
  5. Add automated tests that fail if token, api_key, or equivalent credential fields appear in generated request paths.

T09 · Insecure Skill Coding Practices

Note
Location
src/xiaohongshu/search-cli.js:188
Finding

Automatic Plaintext Persistence of Collected Data and URL Tokens

Content
View full analysis

Vulnerability Details

File Location: src/xiaohongshu/search-cli.js:188-210 and src/utils/log.js:5-38; equivalent automatic writes occur in src/xiaohongshu/detail-cli.js:143-160, src/xiaohongshu/comment-cli.js:143-160, and src/xiaohongshu/post-cli.js:145-162
Vulnerability Type: Unprotected local storage of collected data and sensitive URL parameters
Risk Level: Low

Vulnerable Code

From src/xiaohongshu/search-cli.js:188-210:

javascript
const finalOutput = {
  status: "success",
  error_code: "OK",
  message: "搜索任务完成",
  timestamp: new Date().toLocaleString(),
  request: {
    command: "search",
    keyword: keyword,
    type: type,
    sort: sort,
    time: time,
    limit: limit,
  },
  skill_metadata: {
    skill_version: constants.VERSION,
    runtime_version: process.versions.node,
    execution_time: Date.now() - startTime,
  },
  results: searchTask,
};
console.log(JSON.stringify(finalOutput, null, 2));
utils.printSuccess(
  `搜索任务完成, 共返回 ${finalOutput.results.length} 条结果`,
);

await log.taskWrite(
  `${startTime}_${keyword}_${type}_${sort}_${limit}_search.json`,
  JSON.stringify(finalOutput, null, 2),
);

From src/utils/log.js:5-38:

javascript
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.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.
...[truncated 2851 chars]
Remediation
View remediation

Remediation Suggestions

  1. Make file persistence opt-in through an explicit option such as --output &lt;path&gt;; otherwise return results only through standard output.
  2. Clearly disclose any persistence behavior before collection begins.
  3. When files are requested, create them with restrictive permissions such as mode 0o600 and create the directory with mode 0o700, subject to platform support.
  4. Remove or mask xsec_token and similar URL credentials before writing results.
  5. Avoid placing raw search keywords in filenames; use a random identifier or sanitized non-sensitive task ID.
  6. Define a retention policy and provide a cleanup command or automatic expiration mechanism.
  7. Add logs/ to .gitignore to reduce accidental repository commits.
  8. For sensitive datasets, support encryption at rest or require the caller to provide a protected output destination.
  9. Document which fields are stored, where they are stored, and how users can delete them.
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 (41)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

Based on the supplied code chunk, the implementation visible here is only a generic config file. The most concrete behavioral signal is the BASE_URL set to www.guaikei.com, which is not identified as Xiaohongshu and appears inconsistent with the declared platform-specific purpose. There is no evidence in this chunk of searching Xiaohongshu notes, retrieving note details/comments, or querying blogger works. While a config file alone may be incomplete, with the current evidence the description does not accurately match the actual code shown.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

声明描述的是一个面向小红书内容查询的数据技能,核心能力应包括搜索笔记、读取详情、评论和博主作品等。实际代码仅实现了通用命令行参数解析与帮助文本生成功能,属于基础工具模块,没有任何与小红书、笔记、评论、博主、链接解析或平台数据访问相关的逻辑。因此该代码片段的实际行为与声明用途存在明显不一致,属于主用途 materially different 的情况。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared purpose is a Xiaohongshu content/data access skill, but the supplied code chunk does not search Xiaohongshu, parse links, fetch notes, comments, or creator works. Instead, it validates inputs, sanitizes filenames, creates directories, and writes content to a local log file. File logging can be a supporting implementation detail in a larger skill, but this chunk's actual behavior by itself is materially different from the declared end-user functionality and introduces filesystem write capability that is not reflected in the description. Therefore this code chunk does not accurately represent the declared purpose.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description says this skill should retrieve Xiaohongshu notes, details, comments, and blogger content. However, the supplied code chunk does not implement any of those behaviors. It only accesses the local filesystem to read package.json and return the package name. That is a materially different purpose from the declared user-facing functionality, so this is a clear mismatch based on the provided code.

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 37)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 70)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 90)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 38)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 72)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 92)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 39)May include surrounding context.

md
- "只拉这篇笔记的评论做舆情: node src/xiaohongshu/comment-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 71)May include surrounding context.

md
- "只拉这篇笔记的评论做舆情: node src/xiaohongshu/comment-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 91)May include surrounding context.

md
- "只拉这篇笔记的评论做舆情: node src/xiaohongshu/comment-cli.js --url 'https://www.xiaohongshu.com/explore/xxx?xsec_token=yyy' --limit 100"

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill declares use of a sensitive capability via environment variables (GUAIKEI_API_TOKEN) but does not define an explicit tool scope such as permissions or allowed-tools. This increases the chance that the runtime grants broader-than-necessary access or that reviewers cannot easily verify what the skill is allowed to use.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The trigger conditions are intentionally broad, including cases where the user merely mentions Xiaohongshu content or provides a link without explicitly asking for data retrieval. Over-broad invocation can cause the agent to route ordinary conversational requests into a data-exfiltrating or third-party API workflow unnecessarily, increasing privacy and authorization risk.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The entire README is presented only in Chinese, including usage instructions, warnings, and support details, with no indication that users may choose another language. This can violate language/locale policy expectations when a skill imposes a single language without user opt-in or explicit justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

This code file contains natural-language documentation that forces a specific language context for readers and maintainers. Under the policy, language constraints should either offer user choice or be clearly justified as region-specific; no such justification appears here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This JavaScript file contains natural-language comments and user-facing error/help messages entirely in Chinese, including thrown errors and generated CLI help text. Under the policy rule, forcing a specific language without user choice is a natural-language policy violation unless the locale restriction is explicitly documented and justified, which is not present here.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This utility writes arbitrary caller-supplied string content to a local file path under the skill directory, which exceeds the stated read-only Xiaohongshu data retrieval scope. Although the filename is partially sanitized to reduce path traversal risk, the function still enables persistent local side effects and storage of unvalidated data, which can be abused for unauthorized data retention, disk-filling, or writing sensitive scraped content to disk.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

Multiple user-visible error strings are written only in Chinese, such as '请求失败' and the token guidance message. This forces a specific language/locale without user opt-in or documented justification, which matches the policy-violation category for language constraints.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This JavaScript file contains natural-language comments and error messages exclusively in Chinese, such as the function description and validation errors. Under the policy, forcing a specific language without user opt-in or a documented region-specific justification 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
94% confidence
Finding

The CLI writes full comment results to a local JSON file automatically after successful execution, but does not clearly disclose this behavior to the user. Because the harvested data may contain personal content, usernames, or other sensitive material, silent persistence increases the risk of unintended retention, exposure to other local users/processes, or accidental inclusion in backups and logs.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The CLI persists fetched note details and comments to a local JSON file after successful execution, but the user is not clearly warned that content will be stored on disk. This can expose scraped data, including potentially sensitive comment content or metadata, to other local users, backups, log collectors, or later unintended reuse, especially in shared or automated environments.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The script reads the GUAIKEI_API_TOKEN environment variable to authenticate outbound API operations, but this file provides no explicit user-facing warning at the point of use about credential access beyond a setup note in help text. For code-file review, access to sensitive environment variables should have some visible disclosure, comment, or clearly documented warning tied to the operation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script sends the provided Xiaohongshu profile URL and limit to remote API methods, which is a network operation involving user-supplied data. While progress messages are printed, they do not disclose that the URL is being transmitted to an external service or persisted as part of task processing.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.exposed_secret_literal

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
SKILL.md:15