Back to skill

Security audit

a-stock-data-quant

Security checks across malware telemetry and agentic risk

Overview

Review recommended: the stock-analysis tool is mostly purpose-aligned, but it ships reversible obfuscated API keys and sends stock queries or AI prompts to multiple third-party services without a clear upfront privacy notice.

Before installing, decide whether stock codes, watchlists, research terms, and free-form AI prompts may be sent to the listed third-party finance and AI providers. Remove or replace the bundled config.yaml credentials, prefer environment variables or a secret store, and disable or regularly clear the cache on shared machines.

SkillSpector

By NVIDIA
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (45)

Lp3

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding
The skill advertises and documents capabilities that entail reading local files, writing outputs such as HTML/cache/config files, using environment/configured secrets, and making network requests, but the manifest does not explicitly declare a corresponding permission model. This creates a transparency and containment gap: an agent or user may approve the skill under a narrower trust assumption than the skill actually requires.

Scope Creep

Medium
Confidence
98% confidence
Finding
The manifest's allowedTools list is limited to Bash/Read/Glob/Grep, yet the skill instructs the agent to run Python programs, install packages, clone repositories, and access remote services. This mismatch can cause agents to exceed declared boundaries or fail open if tool-policy enforcement is weak, undermining least-privilege expectations.

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
The skill requires bearer/API keys for GF MCP and Eastmoney AI services, introducing third-party authenticated network access beyond purely local quantitative analysis. Even if legitimate for functionality, this expands the attack surface to secret handling, accidental credential disclosure, and transmission of user prompts or stock queries to external providers.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The README documents commands that send stock codes, search terms, AI prompts, and market/news requests to numerous third-party services, but it does not clearly warn users that their queries and request metadata leave the local environment. In an agent-integrated skill, users may reasonably assume local processing, so the lack of disclosure can cause unintended data exposure, especially for proprietary research queries or sensitive prompts.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The README shows API key configuration examples in config.yaml but does not warn users to keep secrets out of version control, restrict file permissions, or rotate exposed keys. This omission increases the chance that users will paste real credentials into tracked files or shared environments, leading to credential leakage and unauthorized API use.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill extensively sends user queries, stock identifiers, and prompts to many third-party providers and AI services, but the description does not clearly warn users that their requests will leave the local environment. In an agent skill context, this is dangerous because users may assume a local analysis tool while sensitive prompts, strategies, or watchlists are transmitted externally.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The skill implements on-disk CSV/JSON caching of fetched market data without clearly disclosing that data is persisted locally. In a multi-user or shared workstation environment, cached watchlists, queried symbols, and derived datasets may remain accessible after the session and leak user interests or internal research activity.

Vague Triggers

Medium
Confidence
88% confidence
Finding
The skill defines very broad trigger phrases that overlap with ordinary stock-related conversation, increasing the chance that an agent auto-invokes the skill in contexts where the user did not intend tool use. In a network-enabled finance skill, over-broad routing can lead to unnecessary data disclosure, unintended command execution, or reliance on remote services without clear consent.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The skill prominently describes multiple external data sources and AI-backed features, but it does not provide a clear privacy and data-transmission notice explaining that user queries, stock symbols, and possibly configured credentials will be sent to third-party services. In practice, this can mislead users about where their inputs go and whether external providers will process or retain them.

Missing User Warnings

Low
Confidence
93% confidence
Finding
The function makes outbound HTTP requests to a third-party market-data provider without any explicit user-facing disclosure, and it does so over plain HTTP rather than HTTPS. In an agent skill context, undisclosed network egress can leak user-requested symbols, query timing, and environment metadata to external services, while cleartext transport also permits interception or tampering by a network attacker.

Missing User Warnings

Low
Confidence
93% confidence
Finding
This code performs additional outbound requests to another external provider without explicit disclosure to the user, again using plain HTTP. Even though the data requested is market data, silent egress expands the skill's external data-sharing surface and introduces integrity and privacy risk if requests are monitored, redirected, or modified in transit.

Missing User Warnings

Low
Confidence
89% confidence
Finding
The main public API silently falls back to external providers when the primary source fails, without informing the user that additional network destinations may be contacted. In an agent environment this is security-relevant because users and operators may believe only one source is queried, while failures can trigger hidden egress to multiple third parties and broaden exposure of requests and dependency risk.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The HTML report inserts trade data into JavaScript and then writes `t.reason` directly into `row.innerHTML`, which allows untrusted text to be interpreted as HTML. If trade reasons or related fields can be influenced by external data, an attacker could inject script or markup into the generated local report, resulting in stored XSS when the file is opened.

Missing User Warnings

Low
Confidence
92% confidence
Finding
The code sends user-supplied stock identifiers to Baidu over the network without any explicit user-facing disclosure or consent mechanism. While stock codes are generally low-sensitivity data, this still creates an external data-sharing/privacy issue because user queries and usage patterns are exposed to a third-party service.

External Transmission

Medium
Category
Data Exfiltration
Content
}

    try:
        resp = requests.post(url, json=payload, headers=headers, timeout=15)
        resp.raise_for_status()
        data = resp.json()
    except Exception as e:
Confidence
93% confidence
Finding
requests.post(url, json=

External Transmission

Medium
Category
Data Exfiltration
Content
}

    try:
        resp = requests.post(url, json=payload, headers=_get_headers(), timeout=_TIMEOUT)
        resp.raise_for_status()
        outer = resp.json()
Confidence
97% confidence
Finding
requests.post(url, json=

External Transmission

Medium
Category
Data Exfiltration
Content
}

    try:
        resp = requests.post(_F10_URL, json=payload, headers=_get_headers(), timeout=_TIMEOUT)
        resp.raise_for_status()
        d = resp.json()
        if d.get("retcode") != 0:
Confidence
97% confidence
Finding
requests.post(_F10_URL, json=

External Transmission

Medium
Category
Data Exfiltration
Content
"params": {"name": tool, "arguments": arguments},
    }
    try:
        resp = requests.post(url, json=payload, headers=_get_headers(), timeout=_TIMEOUT)
        resp.raise_for_status()
        outer = resp.json()
        result = outer.get("result")
Confidence
96% confidence
Finding
requests.post(url, json=

External Transmission

Medium
Category
Data Exfiltration
Content
"params": {"name": tool, "arguments": arguments},
    }
    try:
        resp = requests.post(url, json=payload, headers=_get_headers(), timeout=_TIMEOUT)
        resp.raise_for_status()
        outer = resp.json()
        result = outer.get("result")
Confidence
96% confidence
Finding
requests.post(url, json=

External Transmission

Medium
Category
Data Exfiltration
Content
"params": {"name": tool, "arguments": arguments},
    }
    try:
        resp = requests.post(url, json=payload, headers=_get_headers(), timeout=_TIMEOUT)
        resp.raise_for_status()
        outer = resp.json()
        result = outer.get("result")
Confidence
96% confidence
Finding
requests.post(url, json=

External Transmission

Medium
Category
Data Exfiltration
Content
"params": {"name": tool, "arguments": arguments},
    }
    try:
        resp = requests.post(url, json=payload, headers=_get_headers(), timeout=_TIMEOUT)
        resp.raise_for_status()
        outer = resp.json()
        result = outer.get("result")
Confidence
96% confidence
Finding
requests.post(url, json=

External Transmission

Medium
Category
Data Exfiltration
Content
"params": {"name": tool, "arguments": arguments},
    }
    try:
        resp = requests.post(url, json=payload, headers=_get_headers(), timeout=_TIMEOUT)
        resp.raise_for_status()
        outer = resp.json()
        result = outer.get("result")
Confidence
96% confidence
Finding
requests.post(url, json=

External Transmission

Medium
Category
Data Exfiltration
Content
"args": args,
    }
    try:
        resp = requests.post(_F10_URL, json=payload, headers=_get_headers(), timeout=_TIMEOUT)
        resp.raise_for_status()
        d = resp.json()
        if d.get("retcode") != 0:
Confidence
97% confidence
Finding
requests.post(_F10_URL, json=

External Transmission

Medium
Category
Data Exfiltration
Content
headers.update(extra_headers)

    try:
        r = requests.post(url, json=payload, headers=headers, timeout=TIMEOUT,
                         proxies={'http': None, 'https': None})
        result = r.json()
        if result.get('code') == 401 or result.get('status', 0) < 0:
Confidence
98% confidence
Finding
requests.post(url, json=

External Transmission

Medium
Category
Data Exfiltration
Content
if extra_headers:
        headers.update(extra_headers)
    try:
        r = requests.post(url, json=payload, headers=headers, timeout=TIMEOUT,
                         proxies={'http': None, 'https': None})
        result = r.json()
        if result.get('code') == 401 or result.get('status', 0) < 0:
Confidence
98% confidence
Finding
requests.post(url, json=

VirusTotal

VirusTotal findings are pending for this skill version.

View on VirusTotal

Static analysis

Detected: suspicious.exposed_secret_literal

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
config.yaml:27

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
README.md:605