Back to skill

Security audit

股票打板筛选

Security checks for vulnerabilities and agentic risk

Overview

This is a narrowly scoped Chinese-language A-share stock screening CLI that fetches public market data and does not use credentials, persistence, or local file access.

Before installing, understand that this tool calls East Money live quote endpoints despite the documentation naming Sina Finance, and its output is Chinese-only. Treat results as market data for screening, not investment advice; the main technical hardening gap is limiting remote response size and properly aborting timed-out requests.

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

T09 · Insecure Skill Coding Practices

Warning
Location
bin/board.js:35
Finding

Unbounded Remote Response Buffering Can Cause Memory Exhaustion

Content
View full analysis

Vulnerability Details

File Location: bin/board.js, lines 35-59
Vulnerability Type: Unbounded network response buffering and incomplete timeout handling
Risk Level: Medium

javascript
const timeout = setTimeout(() => reject(new Error('请求超时')), 15000);
  
const req = https.get(url, { 
  headers: { 
    'Referer': 'https://finance.eastmoney.com',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
  } 
}, (res) => {
  let data = '';
  res.on('data', chunk => data += chunk);
  res.on('end', () => {
    clearTimeout(timeout);
    try {
      const result = parseData(data, type);
      resolve(result);
    } catch (e) {
      reject(e);
    }
  });
});
  
req.on('error', (e) => {
  clearTimeout(timeout);
  reject(e);
});

Technical Analysis

The application accumulates the entire response from a remote quote service in the data string without enforcing a maximum response size. A remote server can therefore return an arbitrarily large or continuously streamed response, causing the Node.js process to consume increasing amounts of memory.

The 15-second timer only rejects the surrounding promise. It does not call req.destroy() or otherwise terminate the active HTTP request. Consequently, response event handlers may continue receiving and buffering data after the promise has timed out.

The application also does not validate the HTTP status code or response content type before buffering and parsing the body. This permits error pages and other unexpected content to consume resources before eventually causing JSON parsing to fail.

Attack Path

  1. A user invokes the board command.
  2. The command connects to the fixed external East Money API endpoint.
  3. The upstream service, or infrastructure capable of compromising that service, responds with an oversized or indefinitely streamed body.
  4. The data event handler repeatedly append ...[truncated 1063 chars]
Remediation
View remediation

Remediation Suggestions

  • Enforce a strict maximum response size appropriate for the expected quote payload.
  • Track the total bytes received and immediately call req.destroy() when the configured limit is exceeded.
  • In the timeout handler, destroy the active request before rejecting the promise.
  • Validate that the response has a successful HTTP status before reading its body.
  • Validate the expected JSON content type where supported by the upstream service.
  • Reject or tightly constrain redirects so the request cannot be redirected to an untrusted destination.
  • Ensure cleanup occurs only once and remove or disable event handlers after timeout or rejection.

Example hardening pattern:

javascript
const MAX_RESPONSE_SIZE = 2 * 1024 * 1024;
let settled = false;

const req = https.get(url, options, (res) => {
  if (res.statusCode !== 200) {
    res.resume();
    req.destroy(new Error(`Unexpected HTTP status: ${res.statusCode}`));
    return;
  }

  let size = 0;
  const chunks = [];

  res.on('data', (chunk) => {
    size += chunk.length;

    if (size > MAX_RESPONSE_SIZE) {
      req.destroy(new Error('Response exceeds maximum allowed size'));
      return;
    }

    chunks.push(chunk);
  });

  res.on('end', () => {
    if (settled) return;
    settled = true;
    clearTimeout(timeout);

    try {
      resolve(parseData(Buffer.concat(chunks).toString('utf8'), type));
    } catch (error) {
      reject(error);
    }
  });
});

const timeout = setTimeout(() => {
  if (settled) return;
  settled = true;
  req.destroy(new Error('Request timed out'));
}, 15000);
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (3)

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill title and all user-facing instructions are written in Chinese, with no indication that other languages are supported or that Chinese is required for a region-specific compliance reason. This creates a natural-language locale constraint without user opt-in, which matches the policy-violation category.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The manifest description says only '筛选A股涨停板及强势股票' ('screen A-share limit-up and strong stocks'), which describes a topic but does not define specific trigger phrases, activation conditions, or exclusions. In a manifest file, this lack of specificity can cause the skill to match broadly on general stock-related requests rather than a clearly bounded invocation context.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The file description and runtime output are written in Chinese, and the tool does not offer any language or locale selection. Under the policy, forcing a specific language without user opt-in is a natural-language policy concern unless the locale restriction is explicitly justified.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.