Back to skill

Security audit

Stock Pulse

Security checks for vulnerabilities and agentic risk

Overview

This stock-analysis skill is not clearly malicious, but it needs review because it gives concrete trading advice and sends credentials/data to externally configured endpoints.

Install only in an isolated environment, use a dedicated low-privilege LLM key, and set LLM_BASE_URL only to a trusted HTTPS provider. Treat all outputs as informational analysis, not financial advice, and assume stock codes, prompts, and any enabled webhook messages may leave your environment.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
handler.py:22
Finding

LLM API Credential Can Be Sent to an Untrusted or Plaintext Endpoint

Content
View full analysis

Vulnerability Details

File Location: handler.py:22-52
Vulnerability Type: Unvalidated outbound endpoint and insecure transmission of credentials
Risk Level: High

python
def build_llm_client():
    api_key = os.getenv("LLM_API_KEY")
    base_url = os.getenv("LLM_BASE_URL", "").rstrip("/")
    model    = os.getenv("LLM_MODEL")

    if not api_key:
        raise RuntimeError("Please set LLM_API_KEY")
    if not base_url:
        raise RuntimeError("Please set LLM_BASE_URL")
    if not model:
        raise RuntimeError("Please set LLM_MODEL")

    return {"api_key": api_key, "base_url": base_url, "model": model}, model


def llm_chat(client, model: str, prompt: str, max_tokens: int = 800) -> str:
    import requests as _req
    url = client["base_url"].rstrip("/") + "/chat/completions"
    payload = {
        "model": model,
        "messages": [{"role": "user", "content": prompt}],
        "temperature": 0.3,
        "max_tokens": max_tokens,
    }
    headers = {
        "Authorization": f"Bearer {client['api_key']}",
        "Content-Type": "application/json",
    }
    resp = _req.post(url, json=payload, headers=headers, timeout=60)
    resp.raise_for_status()
    return resp.json()["choices"][0]["message"]["content"].strip()

Technical Analysis

The application accepts LLM_BASE_URL directly from the runtime environment and uses it as the destination of an outbound HTTP request without validating its scheme or hostname. The request includes LLM_API_KEY in a bearer authorization header.

If the configured URL uses plain HTTP, the credential and request body are transmitted without TLS protection. If an attacker or compromised deployment configuration can alter LLM_BASE_URL, the request can be redirected to an attacker-controlled server. The request body also includes stock codes, prices, indicators, and prompts derived from the user's requested analysis.

S ...[truncated 1751 chars]

Remediation
View remediation

Remediation Suggestions

  1. Parse LLM_BASE_URL with a standard URL parser and require the https scheme.
  2. Maintain an administrator-controlled allowlist of approved LLM hostnames rather than accepting arbitrary destinations.
  3. Reject URLs containing embedded credentials, fragments, unexpected ports, or unsupported components.
  4. Unless explicitly required, reject loopback, link-local, private-network, and metadata-service addresses after DNS resolution.
  5. Revalidate the destination after redirects, or disable redirects entirely for this request.
  6. Use a dedicated, narrowly scoped API key with restrictive quotas and rotation support.
  7. Avoid logging authorization headers and redact credentials from all exception and diagnostic output.
  8. Document precisely which stock-derived data is transmitted to the LLM provider.
  9. Consider constructing the client from a trusted platform configuration rather than an environment variable that less-trusted launchers may modify.

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Unpinned Third-Party Dependencies Create Supply-Chain Risk

Content
View full analysis

Vulnerability Details

File Location: requirements.txt:1-3
Vulnerability Type: Non-reproducible and unbounded dependency resolution
Risk Level: Medium

text
baostock>=0.8.8
pandas>=1.5.0
requests>=2.28.0

Technical Analysis

All dependencies use lower-bound-only version constraints. Consequently, the documented pip install -r requirements.txt command may install any later version available at installation time, including releases that were not reviewed with this Skill.

This makes installations non-reproducible and increases exposure to compromised upstream releases, malicious package maintainer activity, and incompatible behavioral changes. Python packages may execute installation hooks during installation and arbitrary package code when imported.

No typosquatted package name, custom package index, remote archive, or known malicious version was identified in the audited files. The risk arises from permitting future, unreviewed versions rather than from evidence that the currently named packages are malicious.

Attack Path

  1. A dependency publisher account or upstream release process is compromised, or a future release introduces malicious behavior.
  2. The malicious release has a version greater than or equal to the lower bound in requirements.txt.
  3. A user follows the documented installation command.
  4. Package resolution selects the newer, unreviewed release.
  5. Malicious installation hooks execute during installation, or malicious code executes when handler.py imports the package.

Impact Assessment

Dependency installation normally runs with the privileges of the user or environment performing the installation. A malicious package could therefore read files and environment variables available to that user, including the LLM API key when present, perform outbound network requests, modify the Python environment, or alter stock-analysis results.

If installation is p ...[truncated 230 chars]

Remediation
View remediation

Remediation Suggestions

  1. Pin every direct dependency to an exact, reviewed version.
  2. Generate and commit a lock file that records transitive dependency versions.
  3. Record package hashes and install with pip's --require-hashes option.
  4. Retrieve packages only from an approved package index over HTTPS.
  5. Review dependency updates through a controlled process rather than resolving unrestricted future releases during deployment.
  6. Run dependency vulnerability and provenance checks in CI.
  7. Install the Skill in an isolated virtual environment under a non-privileged account.
  8. Regularly rebuild the lock file to apply reviewed security updates without reverting to unbounded constraints.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (20)

Tainted flow: 'url' from os.getenv (line 556, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
90% confidence
Finding

Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Content

Scanner excerpt · handler.py (reported line 50)May include surrounding context.

python
"Authorization": f"Bearer {client['api_key']}",
        "Content-Type": "application/json",
    }
    resp = _req.post(url, json=payload, headers=headers, timeout=60)
    resp.raise_for_status()
    return resp.json()["choices"][0]["message"]["content"].strip()

Tainted flow: 'url' from os.getenv (line 556, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
91% confidence
Finding

The function posts arbitrary content to a webhook URL taken directly from the FEISHU_WEBHOOK_URL environment variable, creating an outbound exfiltration path for generated analysis or user-provided data. In agent environments, environment variables may be broadly configurable, so this can leak sensitive portfolio/watchlist information or become an SSRF-style egress primitive to internal or unintended destinations.

Content

Scanner excerpt · handler.py (reported line 560)May include surrounding context.

python
if not url:
        print("⚠️  未设置 FEISHU_WEBHOOK_URL"); return
    import requests
    requests.post(url, json={"msg_type": "text", "content": {"text": content}})
    print("✅ 已推送到飞书")

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The skill description omits important real behaviors: outbound calls to a configurable LLM endpoint, stock-data retrieval, and webhook pushing, while also overstating analytical capabilities such as '筹码' analysis. This can mislead users and reviewers about what data leaves the environment and what the model is actually doing, creating both data-exposure and trust/safety risks.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill advertises concrete buy/sell/hold signals, target prices, stop-losses, and buy recommendations without any visible financial-risk disclaimer or uncertainty warning. In this context, that is dangerous because users may treat model output as reliable investment advice despite forecast uncertainty, incomplete data, or model error, leading to real financial harm.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The README markets explicit buy/sell signals, target prices, and '明确结论' without any visible disclaimer that outputs are probabilistic analysis rather than reliable financial advice. In a trading context, users may over-trust the tool and act on recommendations as if they were authoritative, increasing risk of financial harm and potential compliance issues.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The documentation encourages pushing analysis to Feishu/WeChat webhooks but does not warn that stock symbols, recommendations, and potentially sensitive user activity will be transmitted to third-party messaging platforms. This can lead to unintended data disclosure, retention by external services, and leakage of trading intent or proprietary analysis workflows.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill declares required environment variables and clearly relies on external network access, but it does not declare any explicit tool scope or permission boundaries. This weakens platform enforcement and user visibility, increasing the risk that the skill can access secrets or make outbound requests beyond what is expected.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The trigger conditions are very broad and can activate on generic stock-related requests without clear limits. In a financial-advice context, overbroad invocation raises the chance of the skill being used inappropriately or unexpectedly, causing users to receive automated trading guidance when they did not explicitly request this specific high-risk behavior.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

Natural-language strings throughout the file, including the module description and user-facing outputs, are exclusively in Chinese. There is no opt-in, language selection mechanism, or documented region-specific justification, which makes the skill enforce a specific language by default.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill transmits stock-analysis prompts and derived data to an external LLM service without any explicit notice or consent flow in the code path. Even if the data is not highly secret, portfolio interests, watchlists, and trading intents can be sensitive, and undisclosed third-party transmission creates privacy and compliance risk.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The skill advertises stock analysis features but also contains outbound webhook push functionality, which expands data flow beyond the stated user-facing purpose. This scope creep is dangerous because users may not expect their analysis outputs to be transmitted off-platform, increasing the risk of silent data disclosure.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
81% confidence
Finding

The skill's core purpose is stock analysis based on a provided stock code, but the code additionally depends on FEISHU_WEBHOOK_URL and STOCK_LIST from the environment to push messages and source a portfolio list. These capabilities are not an obvious requirement of generating analysis for a requested stock and represent extra context-dependent behavior outside the stated scope.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The code can send stock data and generated analysis to a Feishu webhook without any built-in confirmation, preview, or warning. This is dangerous because users may not realize that their analysis results can be forwarded to an external messaging endpoint, enabling accidental disclosure of trading-related information.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
90% confidence
Finding

This is a direct external transmission primitive that sends content to a webhook endpoint. In the context of an analysis skill, such outbound messaging is more dangerous because it can move user trading interests and generated recommendations outside the expected execution boundary with little transparency.

Content

Scanner excerpt · handler.py (reported line 560)May include surrounding context.

python
if not url:
        print("⚠️  未设置 FEISHU_WEBHOOK_URL"); return
    import requests
    requests.post(url, json={"msg_type": "text", "content": {"text": content}})
    print("✅ 已推送到飞书")

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
72% confidence
Finding

All user-facing instructions and examples in the file are in Chinese, and there is no indication that other languages are supported or that the Chinese-only presentation is a justified regional constraint. This can conflict with language/locale policy expectations when a skill forces one language without user opt-in.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
97% confidence
Finding

The dependency is specified with a lower bound only, so builds may resolve to different future versions over time. This weakens supply-chain control and can unexpectedly introduce breaking or vulnerable releases into the skill environment.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
baostock>=0.8.8
pandas>=1.5.0
requests>=2.28.0

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
98% confidence
Finding

Using pandas with only a minimum version makes installations non-reproducible and prevents knowing exactly which code will run. In a security context, this increases exposure to future vulnerable or incompatible releases and complicates incident response.

Content

Scanner excerpt · requirements.txt (reported line 2)May include surrounding context.

text
baostock>=0.8.8
pandas>=1.5.0
requests>=2.28.0

Unverifiable Dependency: pandas has 1 known advisory(ies) (CVE-2020-13091 (** DISPUTED ** pandas through 1.0.3 can unserialize and execute commands from an)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
99% confidence
Finding

Requests is a network-facing library with a long history of security advisories, and leaving it unpinned allows environment-dependent resolution to unknown versions. That creates supply-chain and patch-management uncertainty, especially for a skill likely to fetch market data over HTTP(S).

Content

Scanner excerpt · requirements.txt (reported line 3)May include surrounding context.

text
baostock>=0.8.8
pandas>=1.5.0
requests>=2.28.0

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.