Back to skill

Security audit

investment-advisor

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed stock-analysis helper that fetches market data and outputs recommendations, with no hidden persistence, credential use, or destructive behavior found.

Install only if you want a Chinese-language stock analysis tool that sends queried ticker symbols to Eastmoney services. Treat buy/sell signals, price targets, and position sizes as educational analysis, not personalized financial advice, and avoid letting remote news headlines influence unrelated agent actions.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/fundamental.mjs:89
Finding
Untrusted Remote News Content Is Passed to the Agent Without an Explicit Trust Boundary<![CDATA[ ## Vulnerability Details **File Location**: `scripts/fundamental.mjs:89-105`, `scripts/fundamental.mjs:267-278`, `scripts/analyze.mjs:196-200`, and `SKILL.md:41-43` **Vulnerability Type**: Indirect prompt-injection exposure through untrusted API content **Risk Level**: Medium ### Complete Code Snippet ```javascript async function fetchNews(symbol) { const s = String(symbol); const url = `https://search-api-web.eastmoney.com/search/jsonp?cb=&param=%7B%22uid%22%3A%22%22%2C%22keyword%22%3A%22${s}%22%2C%22type%22%3A%5B%22cmsArticleWebOld%22%5D%2C%22client%22%3A%22web%22%2C%22clientType%22%3A%22web%22%2C%22clientVersion%22%3A%22curr%22%2C%22param%22%3A%7B%22cmsArticleWebOld%22%3A%7B%22searchScope%22%3A%22default%22%2C%22sort%22%3A%22default%22%2C%22pageIndex%22%3A1%2C%22pageSize%22%3A5%7D%7D%7D`; try { const response = await fetch(url); if (!response.ok) return []; const text = await response.text(); const json = text.replace(/^[^(]*\(/, '').replace(/\);?$/, ''); const data = JSON.parse(json); const articles = data.result?.cmsArticleWebOld || []; return articles.map(a => ({ title: a.title, date: a.date, url: a.url })); } catch { return []; } } ``` ```javascript export async function analyzeNewsSentiment(symbol) { const news = await fetchNews(symbol); const recentHeadlines = news.slice(0, 5).map(n => n.title).filter(Boolean); const positiveWords = ['涨', '盈利', '突破', '利好', '增长', '超预期', '上调', '创新高', '大涨', '买入', '领涨', '飙升']; const negativeWords = ['跌', '亏损', '下跌', '利空', '下滑', '不及预期', '下调', '创新低', '大跌', '卖出', '暴跌', '减持']; let score = 0; for (const title of recentHeadlines) { for (const w of positiveWords) if (title.includes(w)) score += 0.2; for (const w of negativeWords) if (title.includes(w)) score -= 0.2; } score = Math.max(-1, Math.min(1, score)); return { overall: score > 0.2 ? 'positive' : score < -0.2 ? 'negative' : ' ...[truncated 2248 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Explicitly document that every field received from external APIs is untrusted data and must never be interpreted as an instruction. 2. Add a Skill-level rule requiring the agent to use headlines only as quoted market data and to ignore requests, commands, URLs, or policy statements embedded in them. 3. Wrap remote text in a clearly delimited structure, such as an `untrustedExternalContent` field. 4. Normalize titles by removing control characters, invisible Unicode formatting characters, and excessive length. 5. Consider excluding raw headlines from the agent prompt when only a numeric sentiment score is needed. 6. Apply output-schema validation and enforce maximum lengths and expected primitive types for all remote fields. 7. Ensure the host agent requires independent user confirmation before performing consequential tool calls prompted by retrieved content. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/fundamental.mjs:44
Finding
Unvalidated Stock Symbols Are Interpolated Directly into API Query Strings<![CDATA[ ## Vulnerability Details **File Location**: `scripts/technical.mjs:14-29`, `scripts/technical.mjs:49-55`, `scripts/fundamental.mjs:6-13`, `scripts/fundamental.mjs:44-50`, `scripts/fundamental.mjs:59-65`, `scripts/fundamental.mjs:74-80`, and `scripts/fundamental.mjs:89-95` **Vulnerability Type**: Query-parameter and remote filter injection **Risk Level**: Low ### Complete Code Snippet ```javascript function getSecId(symbol) { const s = String(symbol); if (/^\d{6}$/.test(s)) { return s.startsWith('6') ? `1.${s}` : `0.${s}`; } if (/^\d\.\d{6}$/.test(s)) return s; return `1.${s}`; } async function fetchHistoricalData(symbol, limit = 200) { const secid = getSecId(symbol); const url = `https://push2his.eastmoney.com/api/qt/stock/kline/get?secid=${secid}&fields1=f1,f2,f3,f4,f5,f6&fields2=f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61&klt=101&fqt=1&end=20500101&lmt=${limit}`; const response = await fetch(url); ``` ```javascript async function fetchFinancialIndicators(symbol) { const s = String(symbol); const marketCode = getMarketCode(s); const url = `https://datacenter.eastmoney.com/securities/api/data/v1/get?reportName=RPT_LICO_FN_CPD&columns=ALL&filter=(SECURITY_CODE%3D%22${s}%22)&pageSize=4&sortColumns=REPORTDATE&sortTypes=-1&client=APP`; try { const response = await fetch(url); if (!response.ok) return null; const data = await response.json(); return data.result?.data || null; } catch { return null; } } ``` ```javascript async function fetchNews(symbol) { const s = String(symbol); const url = `https://search-api-web.eastmoney.com/search/jsonp?cb=&param=%7B%22uid%22%3A%22%22%2C%22keyword%22%3A%22${s}%22%2C%22type%22%3A%5B%22cmsArticleWebOld%22%5D%2C%22client%22%3A%22web%22%2C%22clientType%22%3A%22web%22%2C%22clientVersion%22%3A%22curr%22%2C%22param%22%3A%7B%22cmsArticleWebOld%22%3A%7B%22searchScope%22%3A%22default%22%2C%22sort%22%3A%22default ...[truncated 1838 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Define strict allowlists for every supported symbol format, for example: - Chinese equities: exactly six decimal digits. - Prefixed Chinese equities: only explicitly supported market prefixes followed by six digits. - United States equities: a narrowly defined set of ASCII letters, digits, dots, and hyphens with a conservative length limit. 2. Reject invalid symbols before initiating any network request. 3. Construct URLs with `URL` and `URLSearchParams` instead of string concatenation. 4. Build the search API's JSON parameter with `JSON.stringify`, then allow `URLSearchParams` to encode it. 5. Avoid inserting raw input into Eastmoney filter expressions. Escape according to the API's filter grammar after allowlist validation. 6. Add tests covering ampersands, fragments, quotes, parentheses, percent encoding, control characters, empty values, and excessively long symbols. 7. Limit portfolio and comparison input counts to reduce unintended third-party request amplification. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/analyze.mjs:302
Finding
CLI Error Responses Expose Internal Stack Traces<![CDATA[ ## Vulnerability Details **File Location**: `scripts/analyze.mjs:302-306` **Vulnerability Type**: Internal information disclosure **Risk Level**: Low ### Complete Code Snippet ```javascript } catch (error) { console.error(JSON.stringify({ error: error.message, stack: error.stack })); process.exit(1); } ``` ### Technical Analysis All top-level exceptions are serialized to standard error with the complete JavaScript stack trace. Stack traces commonly contain absolute installation paths, module filenames, function names, line numbers, and runtime implementation details. This information is useful for reconnaissance and may reveal deployment-specific paths that should not be exposed to untrusted callers. The issue is more relevant when stderr is returned by an API wrapper, logged to a shared system, or shown directly in an agent response. ### Attack Path 1. An attacker supplies an invalid symbol or triggers an upstream response that causes an exception. 2. The exception propagates to the top-level `catch` block. 3. The application includes `error.stack` in its JSON error output. 4. The caller receives internal path and runtime details. 5. The disclosed information can support follow-on attacks against the surrounding deployment. ### Impact Assessment The issue discloses implementation and environment metadata but does not directly expose file contents, credentials, or privileged data. It does not grant code execution or elevated privileges. Scope is limited to information present in the generated exception stack and message. ]]>
Remediation
<![CDATA[ ## Remediation Suggestions 1. Return only a stable public error code and a sanitized message in normal operation. 2. Omit `error.stack` unless an explicit debug mode is enabled. 3. Send detailed diagnostics to a protected local logging destination rather than to the caller. 4. Redact absolute paths, query values, and potentially sensitive remote-response details from logs. 5. Ensure any API or agent wrapper does not automatically relay stderr to end users. 6. Use an environment-independent error identifier so operators can correlate a public failure with protected diagnostic logs. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (20)

Vague Triggers

High
Confidence
95% confidence
Finding
The skill metadata declares itself the preferred/default tool for essentially all investment-analysis and investment-decision requests, which is an overly broad activation scope. That can cause the agent to route a wide class of finance-related prompts into a tool that executes local scripts and produces actionable trading guidance, increasing the chance of inappropriate invocation, over-reliance on tool output, and unsafe financial advice generation.

Ae1

High
Category
analysis-evasion
Content
| "帮我分析一下600410" | `node scripts/analyze.mjs 600410 full` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
| "帮我分析一下600410" | `node scripts/analyze.mjs 600410 full` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
| "帮我分析一下600410" | `node scripts/analyze.mjs 600410 full` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
| "帮我分析一下600410" | `node scripts/analyze.mjs 600410 full` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
| "帮我分析一下600410" | `node scripts/analyze.mjs 600410 full` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
| "帮我分析一下600410" | `node scripts/analyze.mjs 600410 full` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
| "帮我分析一下600410" | `node scripts/analyze.mjs 600410 full` |
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
- `scripts/technical.mjs` — 技术面分析模块
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The document defines deterministic scoring, recommendation mapping, and explicit buy/hold/sell outputs without any disclaimer that results are informational only or require human financial judgment. In an investment-advisor skill, this increases the chance that users or downstream agents treat generated outputs as actionable financial advice, creating compliance, suitability, and user-harm risk from misleading or overconfident recommendations.

Vague Triggers

Medium
Confidence
88% confidence
Finding
The README-style examples map broad natural-language requests directly to command execution without guardrails, negative examples, or eligibility checks. This makes the skill more likely to trigger on loosely related prompts and normalize immediate generation of trading signals or portfolio advice, which is risky in a financial-advice context.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The description is written entirely in Chinese and presents the skill as a Chinese-language assistant, with no indication that users may choose another language or that the locale restriction is required. This is a natural-language locale policy concern because it implicitly enforces a specific language without user opt-in.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
The file's top-level description, usage text, and output description are written entirely in Chinese, and later error/report strings are also Chinese-only. This imposes a specific language on users without any opt-in or alternative locale handling, matching the policy category for language or locale violations.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
Comments, labels, error messages, and output summaries throughout the file are written in Chinese, indicating the skill is designed to communicate in a single language by default. There is no visible mechanism offering the user a language preference or documenting that the locale restriction is intentional and limited to a specific justified context.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The module description, comments, error messages, and recommendation strings are written in Chinese, and returned natural-language analysis content is consistently generated only in Chinese. There is no indication of user opt-in, locale selection, or documented justification for restricting outputs to a single language.

Natural-Language Policy Violations

Low
Confidence
88% confidence
Finding
SQP-3 applies to all file types and includes natural-language language/locale policy violations. The content consistently forces a single language presentation and does not indicate user opt-in, alternatives, or a justified region-specific constraint.

Natural-Language Policy Violations

Low
Confidence
93% confidence
Finding
The CLI emits a Chinese-only error message when required arguments are missing. Because there is no visible mechanism for users to select a preferred language, this is a natural-language policy issue rather than a code-security flaw.

Missing User Warnings

Low
Confidence
94% confidence
Finding
The module sends the user-supplied stock symbol to multiple third-party Eastmoney endpoints, which creates a privacy and transparency issue because user inputs are disclosed externally without any notice, consent, or configurable opt-out in this file. While a stock ticker is typically low-sensitivity data, it can still reveal a user's investment interests or research behavior, especially when correlated across repeated requests.

Missing User Warnings

Low
Confidence
88% confidence
Finding
The function constructs a request URL using the provided symbol and sends it to the Eastmoney API via fetch. While this is central to the module's purpose, there is no runtime log, prompt, or inline disclosure in the function itself that user input will be transmitted to a third-party service.

Missing User Warnings

Low
Confidence
87% confidence
Finding
This exported function sends the requested symbol to a remote Eastmoney endpoint but provides no confirmation, visible logging, or function-level warning about the external transmission. The top file comment mentions the API, but the callable interface itself does not clearly disclose the network behavior.

Static analysis

No suspicious patterns detected.