Back to skill

Security audit

小红书关键词搜索采集

Security checks for vulnerabilities and agentic risk

Overview

Review recommended: the skill is mostly a disclosed Xiaohongshu search/export CLI, but it uses unsafe token transport by default and can submit paid collection tasks without an enforced approval gate.

Install only if you are comfortable with this third-party service storing a local token, using your paid point balance, and receiving Xiaohongshu search/export requests. Prefer configuring an HTTPS base URL before login, do not enable insecure TLS except in a trusted test environment, review every quoted charge before submit, and treat exported CSV files and saved tokens as sensitive.

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

Error
Location
src/config.js:18
Finding

Bearer credentials are transmitted over plaintext HTTP by default

Content
View full analysis

Vulnerability Details

File Location: src/config.js:18-23, src/client.js:52-70
Vulnerability Type: Plaintext transmission of authentication credentials
Risk Level: High

Technical Analysis

The default API endpoint uses unencrypted HTTP:

javascript
// Security note: the server's HTTPS certificate is not yet correctly configured.
// The default therefore remains HTTP.
const DEFAULT_BASE_URL = 'http://st.aidata366.com';

The HTTP client attaches the account bearer token to authenticated requests regardless of whether the configured endpoint uses HTTP or HTTPS:

javascript
async request(method, apiPath, opts = {}) {
  const { body, headers = {}, timeoutMs = REQUEST_TIMEOUT_MS } = opts;

  if (!_httpWarned && this.token && this.baseUrl.startsWith('http://')) {
    _httpWarned = true;
    process.stderr.write(
      '[warn] Current service address uses plaintext HTTP; the token will be transmitted in plaintext\n'
    );
  }

  const ctrl = new AbortController();
  const timer = setTimeout(() => ctrl.abort(), timeoutMs);
  let res;
  let payload = null;
  try {
    res = await fetch(this.baseUrl + '/api/v1' + apiPath, {
      method,
      headers: {
        ...(body ? { 'Content-Type': 'application/json' } : {}),
        ...(this.token ? { Authorization: `Bearer ${this.token}` } : {}),
        ...headers,
      },
      body: body ? JSON.stringify(body) : undefined,
      signal: ctrl.signal,
    });

The warning does not block the request or require confirmation. Consequently, every authenticated request made with the default configuration sends the bearer credential without transport encryption. This affects commands including quota, submit, query, export, and logout.

Because bearer tokens grant access based on possession, a network-positioned attacker who captures the header can reuse the credential without learning a password ...[truncated 1570 chars]

Remediation
View remediation

Remediation Suggestions

  1. Configure a valid HTTPS certificate for the service and change DEFAULT_BASE_URL to an HTTPS URL.
  2. Reject authenticated requests when baseUrl uses http://; a stderr warning is not an adequate control for bearer credentials.
  3. If plaintext HTTP must be supported for local development, restrict it to loopback addresses and require an explicit development-only setting.
  4. Do not allow insecure=true in production workflows. Avoid process-wide use of NODE_TLS_REJECT_UNAUTHORIZED=0; use a narrowly scoped TLS configuration or trusted private CA instead.
  5. Rotate existing tokens after deploying HTTPS because tokens previously transmitted over HTTP may already have been exposed.
  6. Consider short-lived, revocable access tokens with narrowly scoped permissions to reduce the impact of interception.

T09 · Insecure Skill Coding Practices

Warning
Location
cli.js:220
Finding

Paid task submission does not enforce the documented user-confirmation boundary

Content
View full analysis

Vulnerability Details

File Location: cli.js:220-236
Vulnerability Type: Missing executable authorization gate for a charged operation
Risk Level: Medium

Technical Analysis

SKILL.md requires the agent to disclose the estimated charge and wait for user confirmation before executing submit. The executable submission path, however, calculates and prints the price and then immediately performs the charged API operation:

javascript
// Read the price before submission and expose the local estimate.
const { price } = await fetchPrice(cfg.baseUrl);
const billUnits = ceilDiv(count, BILL_UNIT);
const estimatedPoints = billUnits * price;

const items = [{ id: 1, payload: { keyword, count, sort, note_type: noteType } }];

const idemSource = `${keyword}|${count}|${sort}|${noteType}`
  + (opts.force ? `|#force:${Date.now()}` : '');
const idempotencyKey = crypto.createHash('sha256')
  .update(idemSource)
  .digest('hex')
  .slice(0, 32);

process.stderr.write(
  `Submitting search task: keyword="${keyword}" count=${count} sort=${sort}\n` +
  `Billing estimate: ${billUnits}×${price}=${estimatedPoints} points\n`
);

const client = new ApiClient({ baseUrl: cfg.baseUrl, token: cfg.token });
const data = await client.submitTask(
  CAPABILITY,
  items,
  idempotencyKey,
  !!opts.force
);

There is no interactive prompt, approval token, confirmation parameter, or persisted authorization record. Printing the estimated charge to stderr only informs the caller; it does not stop submission until the user approves it.

The documentation-level instruction is therefore the sole confirmation control. Any agent automation, accidental invocation, or instruction-driven workflow that directly executes node cli.js submit ... reaches the charged operation without proving that the user accepted the quoted keyword, count, price, sorting mode, or note type.

The idempotency key limits duplicate charges ...[truncated 1340 chars]

Remediation
View remediation

Remediation Suggestions

  1. Split submission into a quote phase and a commit phase.
  2. Have the quote phase return a short-lived server-signed confirmation token bound to:
    • Account identity
    • Keyword
    • Requested count
    • Sorting mode
    • Note type
    • Current unit price and maximum charge
    • Expiration time
  3. Require an explicit option such as --confirm-token <token> before calling submitTask, and reject submissions without a valid token.
  4. For direct human CLI use, display the complete quote and require an affirmative interactive response. For agent use, rely on the signed confirmation token rather than an easily fabricated Boolean flag.
  5. Ensure that --force requires a new confirmation because it creates a fresh idempotency key and can incur another charge.
  6. Enforce the same authorization requirement on the server so alternate clients cannot bypass the CLI-side control.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (12)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The declared purpose is keyword search/export, but the skill also includes broader authentication, account/session handling, config mutation, generic task/export operations, and references to other collection workflows. This mismatch weakens user and agent trust boundaries: an agent may invoke capabilities the user did not intend, including token issuance/storage, account actions, or broader data collection against the same platform.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The client exposes comment-session creation, stepping, listing, and export-style retrieval APIs that are outside the declared skill scope of keyword-based Xiaohongshu search result collection. This creates a capability mismatch: an agent or downstream caller can invoke broader comment-harvesting workflows than users would reasonably expect from the manifest, increasing the risk of overcollection, privacy-impacting data access, and policy bypass through undeclared functionality.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The step-wise comment session controls enable interactive harvesting behavior, including long-running collection operations, that is materially different from simple keyword search result export. In the context of a search-only skill, this hidden control surface increases abuse potential by enabling deeper scraping workflows and incremental data extraction not disclosed to users or reviewers.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill exposes shell, network, and environment-backed behavior but declares no explicit tool scope or permission boundaries. That increases the chance an agent can invoke more capability than intended, especially because the skill performs registration, login, config changes, file writes, and remote HTTP requests to a third-party service.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The invocation description says to use the skill when the user mentions broad phrases like “选题” and “竞品笔记列表,” alongside a long mixed list of scenarios. These triggers are not narrowly bounded and do not include exclusion conditions or negative examples, which could cause the skill to activate for general research conversations rather than explicit requests to run this specific collection workflow.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The CLI allows users to disable HTTPS certificate validation via the persisted insecure setting, and the main flow applies it globally before handling authentication and API calls. In this skill, the client handles login/register session tokens, bearer tokens, quota queries, task submission, and export downloads, so a man-in-the-middle on an untrusted network could intercept or alter credentials, responses, and downloaded data when TLS verification is disabled.

Content

No source excerpt is available for this finding.

Unsafe Defaults

Medium
Category
Tool Misuse
Confidence
90% confidence
Finding

The allowInsecureTls helper disables TLS certificate validation process-wide by setting NODE_TLS_REJECT_UNAUTHORIZED to '0'. That permits man-in-the-middle interception of all subsequent HTTPS requests in the process, which is especially dangerous here because the client sends bearer tokens and may access scraping or export endpoints tied to user accounts.

Content

Scanner excerpt · src/client.js (reported line 17)May include surrounding context.

js
/** 忽略 HTTPS 证书校验 (服务端自签/域名不匹配证书时由 insecure 配置开启)。进程级。 */
function allowInsecureTls() {
  process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
}

/** 业务错误: code 为后端错误码 (1001/1002/3001/...) */

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This code file contains natural-language comments and stderr messages exclusively in Chinese, including operational notices at L75-L76 that users may see during execution. Under the policy rule, forcing a specific language without offering user choice or documenting a justified locale constraint is a language/locale policy violation.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This code automatically imports a token, base URL, and potentially the insecure flag from a different skill’s legacy configuration without explicit user consent. That breaks isolation between skills and can cause credential confusion, unintended account reuse, or silent routing of requests to an inherited endpoint, which is especially risky because this module already defaults to insecure transport settings elsewhere.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This file’s documentation and runtime messages are written in Chinese and the code emits Chinese-only user-facing guidance such as login and timeout instructions. That enforces a specific language/locale in the skill behavior without any visible opt-in or alternative, which matches the language-policy concern for natural-language violations.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
98% confidence
Finding

User-facing descriptions, usage text, prompts, and operational messages are entirely in Chinese, with no indication that another language can be selected. This creates a language/locale constraint without user opt-in, which matches the policy-violation category for forced language choice.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The manifest description at L05 is entirely in Chinese and presents the skill as Chinese-language only, with no indication that users can choose another language or locale. This can violate language/locale policy when the skill is presented in environments expecting neutral or user-selectable language behavior.

Content

No source excerpt is available for this finding.