Back to skill

Security audit

guaikei-xhs-search-notes-get-comments

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent Xiaohongshu public-data CLI, but it needs review because it sends API credentials in URL query strings and automatically saves retrieved data and URLs to plaintext logs.

Review before installing. Use a least-privilege Guaikei token, do not run this with sensitive or regulated research targets unless authorized, and understand that submitted keywords/URLs go to guaikei.com. Run it only in a workspace where plaintext logs are acceptable, clean the logs directory when finished, and rotate the API token if it may have appeared in URL or infrastructure logs.

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 Credential Exposed in URL Query Strings

Content
View full analysis

Vulnerability Details

File Location: src/utils/request.js:76-112, with vulnerable callers in src/api/search.js:20-60, src/api/detail.js:17-51, src/api/comment.js:17-51, and src/api/post.js:17-51
Vulnerability Type: API credential exposure through request URLs
Risk Level: Medium

Vulnerable Code

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

The API modules pass the raw credential in the params object. For example:

js
return await postJson(
  "/api/xiaohongshu/detail/url",
  { _: Date.now(), token: token },
  { url: url, limit: limit },
);
js
const res = await getJson("/api/xiaohongshu/detail/info", {
  _: Date.now(),
  token: token,
  url: url,
  limit: limit,

...[truncated 1894 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove the token property from all URL query parameter objects.

  2. Send credentials in an authorization header, for example:

    js
    headers: {
      "Authorization": `Bearer ${token}`,
      "Content-Type": "application/json",
    }
    
  3. Refactor postJson and getJson to accept authentication separately from ordinary request parameters so credentials cannot accidentally be serialized into URLs.

  4. Redact tokens from application errors, tracing data, debug output, and server telemetry.

  5. Configure reverse proxies and API servers to suppress or sanitize sensitive query parameters while legacy clients remain supported.

  6. Rotate any tokens that may already have been retained in URL or infrastructure logs.

  7. Add automated tests that fail if token, api_key, or authorization credentials appear in generated request paths.

T09 · Insecure Skill Coding Practices

Warning
Location
src/xiaohongshu/detail-cli.js:139
Finding

Automatic Plaintext Persistence of Retrieved Data and Access-Bearing URLs

Content
View full analysis

Vulnerability Details

File Location: src/xiaohongshu/detail-cli.js:139-161 and src/utils/log.js:25-34; equivalent persistence occurs in comment-cli.js:143-160, post-cli.js:145-162, and search-cli.js:188-211
Vulnerability Type: Insecure storage of sensitive data in plaintext files
Risk Level: Medium

Vulnerable Code

js
const finalOutput = {
  status: "success",
  error_code: "OK",
  message: "详情任务完成",
  timestamp: new Date().toLocaleString(),
  request: {
    command: "detail",
    url: url,
    limit: limit,
  },
  skill_metadata: {
    skill_version: constants.VERSION,
    runtime_version: process.versions.node,
    execution_time: Date.now() - startTime,
  },
  results: detailTask,
};
console.log(JSON.stringify(finalOutput, null, 2));
utils.printSuccess(`详情任务完成, 已返回结果`);

await log.taskWrite(
  `${startTime}_${validator.url2Name(url)}_detail.json`,
  JSON.stringify(finalOutput, null, 2),
);

The writer creates an ordinary plaintext file without explicitly restrictive permissions:

js
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(`  → 已保存到 ${outputFilename}`);
} catch (error) {
  utils.printError(`日志写入失败: ${error.message}`);
}

Technical Analysis

Every successful command automatically serializes the full result object to a persistent file under the project-level logs/ directory. In URL-based workflows, the serialized request.url may contain an xsec_token query parameter. The same file may also contain complete note, profile, post, and comment datasets returned by the external service.

The storage is automatic rather than opt-in. The code does not redact access-bearing URL parameters, establi ...[truncated 1699 chars]

Remediation
View remediation

Remediation Suggestions

  1. Make filesystem persistence opt-in through an explicit option such as --output <path>; otherwise, return data only through standard output.

  2. Remove or redact sensitive query parameters before printing or saving URLs, especially xsec_token, token, and similar access credentials.

  3. If output files are requested, create them with owner-only permissions:

    js
    await fs.promises.writeFile(outputFilename, content, {
      encoding: "utf8",
      mode: 0o600,
    });
    
  4. Create the output directory with restrictive permissions where supported.

  5. Document exactly what is persisted, the destination directory, retention expectations, and the user's responsibility for handling collected data.

  6. Add configurable retention and secure cleanup controls.

  7. Add logs/ to .gitignore and relevant backup exclusions where appropriate.

  8. Consider storing only the minimum fields required by the user rather than the complete API response.

  9. Add tests verifying that saved output never contains known sensitive URL parameters.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (58)

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

声明描述的是一个覆盖多类小红书运营分析场景的数据技能,包含爆款挖掘、竞品监控、KOL筛选、评论洞察等较宽泛能力。但给出的代码片段只显示两个接口:创建已发布笔记任务,以及获取已发布笔记结果,输入是博主URL和笔记数量,输出是已发布笔记数据。虽然这可能为部分分析场景提供基础数据,但从该代码本身看,并未体现评论数据抓取、竞品监控逻辑、KOL筛选能力或爆款识别/分析能力。因此代码实际能力明显比声明更窄,属于描述与实际行为不一致。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

声明描述的是一个面向小红书运营分析的数据能力技能,核心应体现为获取、整理或返回小红书相关结构化数据。但提供的代码仅是通用参数解析模块(parseArgs/readValueAfterFlag/buildHelp),属于底层 CLI 支持工具。它没有访问小红书、没有进行爆款挖掘/竞品监控/KOL筛选/评论洞察,也没有任何与业务目标直接相关的数据处理逻辑。因此,代码实际行为与声明用途存在明显且实质性的不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

声明描述的核心能力是为小红书运营决策提供结构化数据支持,但该代码片段的实际职责仅是校验API TOKEN并输出配置/获取TOKEN的提示信息。虽然TOKEN管理可被视为底层支持模块,但从该片段本身看,其行为与声明的业务能力完全不对应,且出现了额外的联系微信获取私有TOKEN提示,这属于未声明且与描述目标无直接关系的行为。因此,该代码片段与声明用途存在明显不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

声明描述的是面向小红书数据分析与运营支持的业务能力,而提供的代码片段实际只是一个本地日志写入工具,没有体现任何小红书数据获取、结构化处理、竞品监控、KOL筛选或评论洞察相关逻辑。虽然日志功能可能是辅助实现细节,但当前代码片段所展现的唯一能力是文件系统写入,这与声明的核心用途明显不一致;且声明中未体现会进行本地文件写入。因此应判定为描述与实际行为不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

声明的核心功能是为小红书运营/营销场景提供数据支持,包括爆款挖掘、竞品监控、KOL筛选和评论洞察。但提供的代码片段只实现了一个工具函数:定位 package.json,读取文件内容,并返回包名。该行为既没有执行任何小红书相关的数据获取或分析,也没有体现结构化数据输出能力。虽然读取 package.json 可能是内部辅助实现,但就当前代码片段所呈现的实际行为而言,其功能与声明的主要用途明显不一致,因此应判定为描述与行为不匹配。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

声明描述的是一个较完整的小红书数据支持技能,面向多种运营决策场景,涵盖爆款挖掘、竞品监控、KOL筛选、评论洞察等多类能力。但当前代码块仅实现了:接受一个小红书博主主页 URL、限制返回数量、创建/获取主页笔记任务,并输出结果。这说明它只是一个“博主主页笔记数据抓取”子功能,而不是声明中的完整能力集合。虽然这仍属于‘拿数据’范畴,与小红书数据相关,但声明显著高于代码实际展现的能力范围,尤其评论、竞品、筛选、洞察等都未在代码中体现,因此应判定为描述与行为不匹配。

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 38)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 54)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 58)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 94)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 149)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 39)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 55)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 94)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 152)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 40)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 56)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 58)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 94)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 155)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
87% confidence
Finding

The skill declares access to a sensitive environment variable (GUAIKEI_API_TOKEN) but does not define an explicit tool scope such as permissions or allowed-tools. That weakens least-privilege guarantees and makes it harder for reviewers or runtimes to understand and constrain what the skill is permitted to access.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill sends user-supplied keywords and Xiaohongshu note/profile URLs to a third-party API service, but the user-facing description does not prominently warn about that data transfer before execution. This creates a transparency and privacy risk, especially when URLs or search terms may reveal business research targets, campaign interests, or other sensitive intent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The README says all task results are automatically written to the logs/ directory but does not clearly warn that search keywords, target URLs, and returned datasets may be persisted on disk. This can create unintended local data exposure, especially on shared workstations, CI runners, synced folders, or endpoints with broad filesystem access.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The document instructs users to configure GUAIKEI_API_TOKEN before running the skill, but it does not clearly disclose that the skill will consume a sensitive credential to access an external service. This can cause users to provide privileged API tokens without informed consent or understanding of scope, increasing the risk of credential misuse, overbroad access, or accidental exposure through logs, shell history, or downstream tooling.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

This code sends the provided API token as part of an HTTP request, which is a safety-relevant network operation involving credentials. While the function parameters are documented, there is no explicit warning, confirmation, or user-facing disclosure here that the token will be transmitted to the remote API.

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:16