Back to skill

Security audit

xhs-competitor-watch

Security checks for vulnerabilities and agentic risk

Overview

The skill is broadly coherent for Xiaohongshu research, but it sends service tokens and Xiaohongshu URLs to a third-party API in exposed query strings and automatically stores full results locally.

Review this before installing if the token or research targets are sensitive. Use a dedicated low-privilege Guaikei token, avoid pasting unnecessary xsec_token query parameters, assume keywords and target URLs are sent to www.guaikei.com, and periodically delete or protect the local logs directory because it stores full outputs.

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

API Credential Exposed in URL Query Strings

Content
View full analysis

Vulnerability Details

File Location: src/utils/request.js:71-92, with credential sources in src/api/search.js:20-29,49-60, src/api/detail.js:17-26,43-52, and src/api/post.js:17-26,43-52
Vulnerability Type: Credential exposure through URL query parameters
Risk Level: Medium

Vulnerable Code

src/utils/request.js:71-92:

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

src/utils/request.js:95-113:

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

A representative credential source appears in src/api/search.js:20-29:

js
async function createSearchTask(token, keyword, type, sort, time, limit) {
  return await withRetry(
    async () => {
      return await postJson(
        "/api/xiao
...[truncated 2496 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove the token from every query-parameter object.
  2. Transmit it through a dedicated authentication header, preferably:
    js
    headers: {
      "Authorization": `Bearer ${token}`,
      "Content-Type": "application/json",
    }
    
  3. Refactor postJson and getJson to accept authentication separately from ordinary request parameters, preventing accidental serialization of secrets into URLs.
  4. Configure client, server, proxy, and monitoring systems to redact Authorization and any legacy token parameter.
  5. Rotate tokens that may already have appeared in access or monitoring logs.
  6. Review and purge retained URL logs containing credentials where operationally and legally appropriate.
  7. Add automated tests asserting that request paths never contain token, secret, password, or authorization credential values.

T09 · Insecure Skill Coding Practices

Note
Location
src/validate/url.js:3
Finding

Xiaohongshu URL Allowlist Bypass Through Substring Matching

Content
View full analysis

Vulnerability Details

File Location: src/validate/url.js:3-44
Vulnerability Type: Improper URL validation and domain allowlist bypass
Risk Level: Low

Vulnerable Code

src/validate/url.js:3-44:

js
function normalizeUrl(url) {
  if (typeof url !== "string" || url.trim() === "") {
    utils.printError(`Xiaohongshu URL cannot be empty`);
    return false;
  }
  url = url.trim();
  url = url.replace("http://", "https://");
  if (url.indexOf("https://") !== 0) {
    utils.printError(`Xiaohongshu URL must start with https://`);
    return false;
  }
  if (url.indexOf(" ") !== -1) {
    utils.printError(`Xiaohongshu URL cannot contain spaces`);
    return false;
  }
  return true;
}

function isNoteUrl(url) {
  if (!normalizeUrl(url)) return false;
  if (url.indexOf("https://www.xiaohongshu.com/explore/") !== -1) {
    return true;
  } else if (url.indexOf("https://xhslink.com/m/") !== -1) {
    return true;
  } else if (url.indexOf("https://xhslink.cn/m/") !== -1) {
    return true;
  } else {
    return false;
  }
}

function isProfileUrl(url) {
  if (!normalizeUrl(url)) return false;
  if (url.indexOf("https://www.xiaohongshu.com/user/profile/") !== -1) {
    return true;
  } else if (url.indexOf("https://xhslink.com/m/") !== -1) {
    return true;
  } else if (url.indexOf("https://xhslink.cn/m/") !== -1) {
    return true;
  } else {
    return false;
  }
}

The accepted value is subsequently submitted to the external service. For example, src/api/detail.js:17-26 contains:

js
async function createDetailTask(token, url, limit) {
  return await withRetry(
    async () => {
      return await postJson(
        "/api/xiaohongshu/detail/url",
        { _: Date.now(), token: token },
        { url: url, limit: limit },
      );
    },

Technical Analysis

isNoteUrl and isProfileUrl use `String.indexOf ...[truncated 2219 chars]

Remediation
View remediation

Remediation Suggestions

  1. Parse input with the standard URL class rather than searching raw strings:
    js
    const parsed = new URL(url);
    
  2. Require parsed.protocol === "https:".
  3. Compare parsed.hostname exactly against an explicit allowlist such as:
    js
    const allowedHosts = new Set([
      "www.xiaohongshu.com",
      "xhslink.com",
      "xhslink.cn",
    ]);
    
  4. Validate pathname prefixes separately:
    • /explore/ for note URLs
    • /user/profile/ for profile URLs
    • /m/ for approved short-link hosts
  5. Reject embedded credentials, unexpected ports, malformed encoding, and hostnames that merely end with or contain an approved hostname.
  6. Return the canonical normalized URL and ensure callers submit that validated value rather than the original raw input.
  7. Apply equivalent validation on the remote API. Client-side checks must not be treated as a security boundary.
  8. Add negative tests for URLs that contain approved strings in attacker-controlled paths, queries, usernames, fragments, or subdomains.
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 (45)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

Advertising competitor monitoring and comparative analytics while functioning only as a generic search CLI is materially misleading in a security-sensitive agent setting. Even absent obvious exploit code, this creates a review blind spot: operators may approve network/API usage believing it is constrained to one workflow when behavior and data handling are different in practice.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

Advertising competitor monitoring and comparative analytics while functioning only as a generic search CLI is materially misleading in a security-sensitive agent setting. Even absent obvious exploit code, this creates a review blind spot: operators may approve network/API usage believing it is constrained to one workflow when behavior and data handling are different in practice.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

Advertising competitor monitoring and comparative analytics while functioning only as a generic search CLI is materially misleading in a security-sensitive agent setting. Even absent obvious exploit code, this creates a review blind spot: operators may approve network/API usage believing it is constrained to one workflow when behavior and data handling are different in practice.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Advertising competitor monitoring and comparative analytics while functioning only as a generic search CLI is materially misleading in a security-sensitive agent setting. Even absent obvious exploit code, this creates a review blind spot: operators may approve network/API usage believing it is constrained to one workflow when behavior and data handling are different in practice.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

Advertising competitor monitoring and comparative analytics while functioning only as a generic search CLI is materially misleading in a security-sensitive agent setting. Even absent obvious exploit code, this creates a review blind spot: operators may approve network/API usage believing it is constrained to one workflow when behavior and data handling are different in practice.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

Advertising competitor monitoring and comparative analytics while functioning only as a generic search CLI is materially misleading in a security-sensitive agent setting. Even absent obvious exploit code, this creates a review blind spot: operators may approve network/API usage believing it is constrained to one workflow when behavior and data handling are different in practice.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

Advertising competitor monitoring and comparative analytics while functioning only as a generic search CLI is materially misleading in a security-sensitive agent setting. Even absent obvious exploit code, this creates a review blind spot: operators may approve network/API usage believing it is constrained to one workflow when behavior and data handling are different in practice.

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 107)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 241)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 108)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 253)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"

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

This manifest presents the skill entirely in Chinese in the user-facing description and keywords, which can amount to a language/locale policy violation when no opt-in, alternative language, or explicit region-specific justification is provided. The file gives no indication that the skill is intentionally limited to Chinese-speaking users or a China-specific compliance context.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The manifest describes a focused skill for Xiaohongshu competitor monitoring via keyword search and competitor post analysis. The README expands the skill's claimed purpose to include explosive-note mining, trend prediction, KOL screening, and even comment analysis for Douyin, which materially broadens the represented behavior beyond the manifest scope.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The documentation frames the tool as a Xiaohongshu-focused data-mining and competitor-monitoring utility, yet the capability table includes '获取抖音评论详情' for Douyin comment analysis. This is an active contradiction in the file's own stated intent and platform scope, not merely an omitted detail.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The README states that all task results are automatically saved to the logs directory, but does not clearly warn that searched keywords, profile/note URLs, comments, or analysis outputs may be persisted locally. In a competitor-monitoring workflow, these artifacts can reveal sensitive business intent, targets, research history, and possibly third-party content, increasing confidentiality and privacy risk if the host is shared or logs are later exported.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The changelog is entirely written in Chinese, and there is no indication that the skill offers a language choice or that the Chinese-only presentation is required for a documented regional context. Under the language/locale policy, forcing a specific language without user opt-in can be a natural-language policy violation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The document encourages passing full Xiaohongshu note/profile URLs, including examples with xsec_token query parameters, but does not warn users that these URLs and tokens may be transmitted to an external service/API. Query-token data can be sensitive or session-like, and exposing it without notice increases the risk of unintended credential leakage, account correlation, or unauthorized reuse if logs, prompts, or downstream systems retain the values.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This JavaScript file contains natural-language comments, error messages, and generated help text exclusively in Chinese, including user-facing strings such as parameter errors and usage labels. Per the policy, forcing a specific language without offering a choice or documenting a justified locale 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
96% confidence
Finding

The user-facing error and info strings are entirely in Chinese, which imposes a specific language on users without any opt-in or fallback. This matches the policy category for language/locale constraints that are not optional or justified as region-specific.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Multiple thrown error messages are written only in Chinese, such as 请求失败, 响应解析失败, and path/params validation text. This forces a specific language for user-visible output without user opt-in or documented locale constraints.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The code performs outbound HTTPS GET and POST requests and serializes caller-provided parameters and JSON payloads for transmission. In this file there is no confirmation prompt, logging, comment, or docstring disclosing that user or system data may be sent over the network.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This CLI retrieves detailed note data including comments and then persists the full result locally, which goes beyond a narrow competitor-monitoring description focused on content strategy metrics. Comments can contain personal data or sensitive user-generated content, so collecting and storing them expands the skill’s data exposure and privacy risk.

Content

No source excerpt is available for this finding.